package org.jeecg.modules.business.repertory.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysDepartModel;
import org.jeecg.common.util.BeanUtil;
import org.jeecg.modules.basic.customer.entity.BasicCustomer;
import org.jeecg.modules.basic.customer.service.IBasicCustomerService;
import org.jeecg.modules.basic.material.entity.BasicMaterial;
import org.jeecg.modules.basic.material.service.IBasicMaterialService;
import org.jeecg.modules.basic.plant.entity.WmsSapWarehouseMap;
import org.jeecg.modules.basic.plant.service.IWmsSapWarehouseMapService;
import org.jeecg.modules.basic.supplier.entity.BasicSupplier;
import org.jeecg.modules.basic.supplier.service.IBasicSupplierService;
import org.jeecg.modules.basic.unit.entity.BasicUnit;
import org.jeecg.modules.basic.unit.service.IBasicUnitService;
import org.jeecg.modules.basic.warehouse.entity.WmsBasicWarehouse;
import org.jeecg.modules.basic.warehouse.entity.WmsBasicWarehouseArea;
import org.jeecg.modules.basic.warehouse.entity.WmsBasicWarehouseAreaLocation;
import org.jeecg.modules.basic.warehouse.service.IWmsBasicWarehouseAreaService;
import org.jeecg.modules.basic.warehouse.service.IWmsBasicWarehouseService;
import org.jeecg.modules.basic.warehouse.service.impl.WmsBasicWarehouseAreaLocationServiceImpl;
import org.jeecg.modules.basic.warehouse.service.impl.WmsBasicWarehouseAreaServiceImpl;
import org.jeecg.modules.basic.warehouseGroup.service.IWmsBasicWarehouseGroupUserService;
import org.jeecg.modules.business.delivery.entity.WmsDeliveryTask;
import org.jeecg.modules.business.delivery.service.IWmsDeliveryTaskService;
import org.jeecg.modules.business.doc.business.entity.WmsInReceipt;
import org.jeecg.modules.business.doc.business.entity.WmsInReceiptMaterial;
import org.jeecg.modules.business.doc.business.service.IWmsInReceiptMaterialService;
import org.jeecg.modules.business.doc.business.service.IWmsInReceiptService;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceipt;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceiptMaterial;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptMaterialService;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptService;
import org.jeecg.modules.business.repertory.entity.WmsInTransitRepertory;
import org.jeecg.modules.business.repertory.entity.WmsRepertory;
import org.jeecg.modules.business.repertory.entity.WmsRepertoryFreezeHistory;
import org.jeecg.modules.business.repertory.entity.WmsRepertoryLockHistory;
import org.jeecg.modules.business.repertory.entity.vo.*;
import org.jeecg.modules.business.repertory.entity.vo.param.RepertoryParamVO;
import org.jeecg.modules.business.repertory.entity.vo.param.RepertoryTcParamVO;
import org.jeecg.modules.business.repertory.mapper.WmsRepertoryMapper;
import org.jeecg.modules.business.repertory.service.IWmsInTransitRepertoryService;
import org.jeecg.modules.business.repertory.service.IWmsRepertoryFreezeHistoryService;
import org.jeecg.modules.business.repertory.service.IWmsRepertoryLockHistoryService;
import org.jeecg.modules.business.repertory.service.IWmsRepertoryService;
import org.jeecg.modules.business.transfer.entity.WmsMoveReceipt;
import org.jeecg.modules.business.transfer.entity.WmsMoveReceiptMaterial;
import org.jeecg.modules.business.transfer.service.IWmsMoveReceiptMaterialService;
import org.jeecg.modules.business.transfer.service.IWmsMoveReceiptService;
import org.jeecg.modules.business.warehouse.entity.WmsInReceiptTaskMaterial;
import org.jeecg.modules.business.warehouse.service.IWmsInReceiptTaskMaterialService;
import org.jeecg.modules.dock.entity.dto.request.MaterialBatchPeculiarityDTO;
import org.jeecg.modules.dock.entity.dto.response.MaterialBatchPeculiarityResponseDTO;
import org.jeecg.modules.dock.entity.mes.request.RepertoryRequestParam;
import org.jeecg.modules.dock.entity.mes.response.MesBaseResponseVO;
import org.jeecg.modules.dock.service.SapDockingRepeaterService;
import org.jeecg.modules.flow.callback.inbound.mapper.MaterialInfoVO;
import org.jeecg.modules.flow.callback.inbound.mapper.WmsValidMapper;
import org.jeecg.modules.flow.callback.outbound.util.CommonOutboundUtil;
import org.jeecg.modules.flow.sys.entity.dto.BaseFlowDto;
import org.jeecg.modules.flow.sys.service.WorkFlowService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.jeecg.common.constant.CommonConstant.DEL_FLAG_1;

/**
 * @Description: 库存
 * @Author: jeecg-boot
 * @Date: 2023-07-31
 * @Version: V1.0
 */
@Service
@Slf4j
public class WmsRepertoryServiceImpl extends ServiceImpl<WmsRepertoryMapper, WmsRepertory> implements IWmsRepertoryService {

    public static final String NORMAL = "normal";
    public static final String FREEZE = "freeze";
    public static final String LOCK = "lock";
    public static final String SUPPLIER = "3";
    public static final String CLIENT = "2";
    public static final String ORGANIZATION = "1";
    private final String[] noUpdateStock = {"R18", "R19", "R21", "C17", "C20"};
    @Resource
    private WmsRepertoryMapper wmsRepertoryMapper;
    @Autowired
    private IWmsRepertoryLockHistoryService wmsRepertoryLockHistoryService;
    @Autowired
    private WmsBasicWarehouseAreaServiceImpl warehouseAreaService;
    @Autowired
    private WmsBasicWarehouseAreaLocationServiceImpl warehouseAreaLocationService;
    @Autowired
    private IWmsRepertoryFreezeHistoryService wmsRepertoryFreezeHistoryService;
    @Autowired
    private IBasicMaterialService materialService;
    @Autowired
    private IWmsBasicWarehouseService warehouseService;
    @Autowired
    private IBasicUnitService unitService;
    @Autowired
    private IWmsInReceiptService inReceiptService;
    @Autowired
    private IWmsInReceiptMaterialService inReceiptMaterialService;
    @Autowired
    private IWmsMoveReceiptService moveReceiptService;
    @Autowired
    private IWmsMoveReceiptMaterialService moveReceiptMaterialService;
    @Autowired
    private IBasicSupplierService supplierService;
    @Autowired
    private IBasicCustomerService customerService;
    @Resource
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private IWmsOutReceiptMaterialService outReceiptMaterialService;
    @Autowired
    private IWmsOutReceiptService outReceiptService;
    @Autowired
    private CommonOutboundUtil commonOutboundUtil;
    @Autowired
    private IWmsBasicWarehouseAreaService wmsBasicWarehouseAreaService;
    @Autowired
    private IWmsSapWarehouseMapService wmsSapWarehouseMapService;
    @Autowired
    private IBasicMaterialService basicMaterialService;
    @Autowired
    private IBasicCustomerService basicCustomerService;
    @Autowired
    private IBasicUnitService basicUnitService;
    @Autowired
    private IWmsInTransitRepertoryService inTransitRepertoryService;
    @Autowired
    private IWmsInReceiptTaskMaterialService wmsInReceiptTaskMaterialService;
    @Autowired
    private IWmsInReceiptMaterialService wmsInReceiptMaterialService;

    @Autowired
    private WorkFlowService workFlowService;
    @Autowired
    private IWmsBasicWarehouseGroupUserService warehouseGroupUserService;

    @Value("${material.code.khtl:}")
    private String khtlCode;

    @Value("${material.code.bzxjl:}")
    private String bzxjlCode;

    @Resource
    private IWmsDeliveryTaskService deliveryTaskService;

    @Autowired
    @Lazy
    private SapDockingRepeaterService sapDockingRepeaterService;


    @Resource
    private WmsValidMapper wmsValidMapper;

    private static void extracted(WmsRepertory repertory) {
        repertory.setBatchCode(null);
        repertory.setSteelCode(null);
        repertory.setOutsideDiameter(null);
        repertory.setWidth(null);
        repertory.setLength(null);
        repertory.setThickness(null);
        repertory.setShopSign(null);
        repertory.setAppearanceGrade(null);
        repertory.setIronLoss(null);
        repertory.setMeasuredThickness(null);
        repertory.setMeasuredIronLoss(null);
        repertory.setScore(null);
        repertory.setOriginalWeight(null);
        repertory.setMeasuredWeight(null);
        repertory.setWarehouseDate(null);
        repertory.setGrossWeight(null);
        repertory.setSaleOrderCode(null);
        repertory.setSaleOrderLineCode(null);
        repertory.setProductCode(null);
        repertory.setProductLineCode(null);
        repertory.setStatus(null);
        repertory.setStatus(null);
        repertory.setStockOrg(null);
        repertory.setOwnerType(null);
        repertory.setOwnerCode(null);
        repertory.setOwnerName(null);
        repertory.setMaterialId(null);
        repertory.setMaterialCode(null);
        repertory.setMaterialName(null);
        repertory.setWmsBasicUnitId(null);
        repertory.setSpecification(null);
    }

    /**
     * 对数据进行处理
     *
     * @param update
     * @return java.util.List<org.jeecg.modules.business.repertory.entity.WmsRepertory>
     * @author hansen
     * @since 2023/9/6 13:30
     */
    private static List<WmsRepertory> extracted(ArrayList<WmsRepertory> update) {
        // 分组
        Map<String, List<WmsRepertory>> collect = update.stream()
                .collect(Collectors.groupingBy(out -> out.getBatchCode() + out.getMaterialId()
                        + out.getWmsBasicWarehouseId() + out.getWmsBasicWarehouseAreaId() + out.getWmsBasicWarehouseAreaLocationId()));
        // 计算库存量, 可用量, 锁定量
        return collect.values().stream().map(list -> {
            BigDecimal stockQuantity = list.stream()
                    .filter(o -> ObjectUtil.isNotNull(o.getStockQuantity()))
                    .map(WmsRepertory::getStockQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            WmsRepertory repertory = list.get(0);
            repertory.setStockQuantity(stockQuantity);
            repertory.setUsableQuantity(stockQuantity);
            repertory.setLockQuantity(BigDecimal.ZERO);
            return repertory;
        }).collect(Collectors.toList());
    }

    /**
     * 给即时库存VO进行赋值
     *
     * @param organization
     * @param ownerType
     * @param owner
     * @param remark
     * @param inReceiptMaterial
     * @param r
     * @param material
     * @author hansen
     * @since 2023/8/22 13:22
     */
    private static WmsRepertory inReceipt(String organization, String ownerType, String owner, String remark, WmsInReceiptMaterial inReceiptMaterial, RepertoryVO r, BasicMaterial material, String code) {
        WmsRepertory repertory = new WmsRepertory();
        String[] ignore = {"id", "batchCode", "receivableQuantity"};
        BeanUtils.copyProperties(inReceiptMaterial, repertory, ignore);
        repertory.setOwnerCode(code);
        repertory.setMaterialName(material.getName());
        repertory.setMaterialCode(material.getCode());
        repertory.setWmsBasicWarehouseId(r.getWmsBasicWarehouseId());
        repertory.setWmsBasicWarehouseAreaId(r.getWmsBasicWarehouseAreaId());
        repertory.setWmsBasicWarehouseAreaLocationId(r.getWmsBasicWarehouseAreaLocationId());
        repertory.setStockQuantity(r.getStockQuantity());
        repertory.setUsableQuantity(r.getStockQuantity());
        repertory.setLockQuantity(BigDecimal.ZERO);
        repertory.setWarehouseDate(new Date());
        repertory.setStockOrg(organization);
        repertory.setStatus(NORMAL);
        repertory.setRemark(remark);
        repertory.setOwnerType(ownerType);
        repertory.setOwnerName(owner);
        repertory.setMaterialId(r.getWmsBasicMaterialId());
        repertory.setWrappage(inReceiptMaterial.getVehicle());
        repertory.setNewestInboundTime(new Date());
        repertory.setSpecification(r.getSpecification());
        repertory.setSupplier(r.getSupplier());
        if (StringUtils.isNotBlank(inReceiptMaterial.getMeasuredWeight())) {
            repertory.setMeasuredWeight(NumberUtils.createBigDecimal(inReceiptMaterial.getMeasuredWeight()));
        }
        if (StringUtils.isNotBlank(inReceiptMaterial.getMeasuredIronLoss())) {
            repertory.setMeasuredIronLoss(NumberUtils.createBigDecimal(inReceiptMaterial.getMeasuredIronLoss()));
        }
        repertory.setSteelCode(inReceiptMaterial.getSteelCoilNumber());
        if (StringUtils.isNotBlank(inReceiptMaterial.getIronLoss())) {
            repertory.setIronLoss(NumberUtils.createBigDecimal(inReceiptMaterial.getIronLoss()));
        }
        if (StringUtils.isNotBlank(inReceiptMaterial.getOriginalWeight())) {
            repertory.setOriginalWeight(NumberUtils.createBigDecimal(inReceiptMaterial.getOriginalWeight()));
        }
        repertory.setUnitSub(inReceiptMaterial.getUnitAssistId());
        repertory.setSaleOrderCode(inReceiptMaterial.getSaleOrderNumber());
        repertory.setSaleOrderLineCode(inReceiptMaterial.getSaleOrderLineNumber());
        repertory.setProductCode(inReceiptMaterial.getProductNumber());
        repertory.setProductLineCode(inReceiptMaterial.getProductLineNumber());
        repertory.setBatchCode(r.getBatchCode());
        repertory.setStockQuantitySub(ObjectUtil.isNull(r.getStockQuantitySub()) ? BigDecimal.ZERO : r.getStockQuantitySub());
        repertory.setUsableQuantitySub(ObjectUtil.isNull(r.getStockQuantitySub()) ? BigDecimal.ZERO : r.getStockQuantitySub());
        repertory.setLockQuantitySub(BigDecimal.ZERO);
        repertory.setLocation(inReceiptMaterial.getLocation());
        repertory.setPlanProductOrderNumber(inReceiptMaterial.getPlanProductOrderNumber());
        return repertory;
    }

    /**
     * 给即时库存VO进行赋值
     *
     * @param organization
     * @param ownerType
     * @param owner
     * @param remark
     * @param wmsMoveReceiptMaterial
     * @param r
     * @param material
     * @param transferToWarehouseId
     * @param code
     * @return org.jeecg.modules.business.repertory.entity.WmsRepertory
     * @author hansen
     * @since 2023/8/31 13:16
     */
    private static WmsRepertory moveReceipt(String organization, String ownerType, String owner, String remark, WmsMoveReceiptMaterial wmsMoveReceiptMaterial, RepertoryVO r, BasicMaterial material, String transferToWarehouseId, String code) {
        WmsRepertory repertory = new WmsRepertory();
        String[] ignore = {"id", "batchCode", "receivableQuantity"};
        BeanUtils.copyProperties(wmsMoveReceiptMaterial, repertory, ignore);
        repertory.setOwnerCode(code);
        repertory.setMaterialName(material.getName());
        repertory.setMaterialCode(material.getCode());
        repertory.setWmsBasicWarehouseId(transferToWarehouseId);
        repertory.setWmsBasicWarehouseAreaId(r.getWmsBasicWarehouseAreaId());
        repertory.setWmsBasicWarehouseAreaLocationId(r.getWmsBasicWarehouseAreaLocationId());
        repertory.setStockQuantity(r.getStockQuantity());
        repertory.setUsableQuantity(r.getStockQuantity());
        repertory.setLockQuantity(BigDecimal.ZERO);
        repertory.setWarehouseDate(new Date());
        repertory.setStockOrg(organization);
        repertory.setStatus(NORMAL);
        repertory.setRemark(remark);
        repertory.setOwnerType(ownerType);
        repertory.setOwnerName(owner);
        repertory.setMaterialId(r.getWmsBasicMaterialId());
        repertory.setWrappage(wmsMoveReceiptMaterial.getPaperTube());
        repertory.setNewestInboundTime(new Date());
        repertory.setSpecification(r.getSpecification());
        repertory.setSupplier(r.getSupplier());
        repertory.setWmsBasicSupplierId(r.getWmsBasicSupplierId());
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getGrossWeight())) {
            repertory.setGrossWeight(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getGrossWeight()));
        }
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getOutsideDiameter())) {
            repertory.setOutsideDiameter(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getOutsideDiameter()));
        }
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getWidth())) {
            repertory.setWidth(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getWidth()));
        }
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getLength())) {
            repertory.setLength(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getLength()));
        }
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getThickness())) {
            repertory.setThickness(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getThickness()));
        }
        repertory.setSteelCode(wmsMoveReceiptMaterial.getSteelCoilNumber());
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getIronLoss())) {
            repertory.setIronLoss(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getIronLoss()));
        }
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getMeasuredThickness())) {
            repertory.setMeasuredThickness(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getMeasuredThickness()));
        }
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getMeasuredIronLoss())) {
            repertory.setMeasuredIronLoss(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getMeasuredIronLoss()));
        }
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getOriginalWeight())) {
            repertory.setOriginalWeight(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getOriginalWeight()));
        }
        if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getMeasuredWeight())) {
            repertory.setMeasuredWeight(NumberUtils.createBigDecimal(wmsMoveReceiptMaterial.getMeasuredWeight()));
        }
        repertory.setSaleOrderCode(wmsMoveReceiptMaterial.getSaleOrderNumber());
        repertory.setSaleOrderLineCode(wmsMoveReceiptMaterial.getSaleOrderLineNumber());
        repertory.setProductCode(wmsMoveReceiptMaterial.getProductNumber());
        repertory.setProductLineCode(wmsMoveReceiptMaterial.getProductLineNumber());
        repertory.setBatchCode(r.getBatchCode());
        repertory.setSpecification(r.getSpecification());
        repertory.setStockQuantitySub(ObjectUtil.isNull(r.getStockQuantitySub()) ? BigDecimal.ZERO : r.getStockQuantitySub());
        repertory.setUsableQuantitySub(ObjectUtil.isNull(r.getStockQuantitySub()) ? BigDecimal.ZERO : r.getStockQuantitySub());
        repertory.setLockQuantitySub(BigDecimal.ZERO);
        return repertory;
    }

    public static String addZero(String code) {
        final int num = 18;
        if (org.apache.commons.lang3.StringUtils.isBlank(code)) {
            return "";
        }
        if (code.length() < 18) {
            int addNum = num - code.length();
            StringBuffer stringBuffer = new StringBuffer("");
            for (int i = 0; i < addNum; i++) {
                stringBuffer.append("0");
            }
            return stringBuffer.append(code).toString();
        }
        return code;
    }

    @Override
    public IPage<RepertoryVO> listByPage(Page<RepertoryVO> pageList, RepertoryParamVO param) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (!"admin".equals(sysUser.getUsername())) {
            List<String> warehouseIds = warehouseGroupUserService.listWarehouseByLoginUser();
            if (CollectionUtils.isEmpty(warehouseIds)) {
                return new Page<>();
            }
            param.setUserWarehouseIds(warehouseIds);
        }
        IPage<RepertoryVO> res = wmsRepertoryMapper.getPage(pageList, param);
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void lock(WmsRepertory wmsRepertory) {
        if (wmsRepertory.getLockQuantity().compareTo(BigDecimal.ZERO) > 0 || wmsRepertory.getLockQuantitySub().compareTo(BigDecimal.ZERO) > 0) {
            // 获取当前登录用户
            LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            // 创建对象并赋值
            WmsRepertoryLockHistory wmsRepertoryLockHistory = new WmsRepertoryLockHistory();
            wmsRepertoryLockHistory.setLockType("1");
            wmsRepertoryLockHistory.setOperationType("1");
            wmsRepertoryLockHistory.setOperator(user.getUsername());
            wmsRepertoryLockHistory.setOperatorDate(new Date());
            wmsRepertoryLockHistory.setWmsRepertoryId(wmsRepertory.getId());
            wmsRepertoryLockHistory.setRemark(wmsRepertory.getRemark());
            wmsRepertoryLockHistory.setLockQuantityMain(wmsRepertory.getLockQuantity());
            wmsRepertoryLockHistory.setLockQuantitySub(wmsRepertory.getLockQuantitySub());
            // 添加一条锁库日志
            wmsRepertoryLockHistoryService.save(wmsRepertoryLockHistory);
            WmsRepertory byId = this.getById(wmsRepertory.getId());
            if (ObjectUtil.isNotNull(wmsRepertory.getLockQuantity())) {
                // 判断输入的锁定量是否大于当前可用量
                if (wmsRepertory.getLockQuantity().compareTo(byId.getUsableQuantity()) == DEL_FLAG_1) {
                    throw new JeecgBootException("锁库量不能大于当前可用量!");
                }
                if (wmsRepertory.getLockQuantity().compareTo(BigDecimal.ZERO) > 0) {
                    if (ObjectUtil.isNull(byId.getUsableQuantity())) {
                        byId.setUsableQuantity(BigDecimal.ZERO);
                    }
                    if (ObjectUtil.isNull(byId.getLockQuantity())) {
                        byId.setLockQuantity(BigDecimal.ZERO);
                    }
                    // 计算当前可用量并重新赋值(当前可用量为: 可用量减去锁定量)
                    byId.setUsableQuantity(byId.getUsableQuantity().subtract(wmsRepertory.getLockQuantity()));
                    // 计算锁定量并重新赋值(当前锁定量为: 传入锁定量加原库存锁定量)
                    byId.setLockQuantity(byId.getLockQuantity().add(wmsRepertory.getLockQuantity()));
                    // 修改库存状态为冻结
                    byId.setStatus(NORMAL);
                }
            }
            if (ObjectUtil.isNotNull(wmsRepertory.getLockQuantitySub())) {
                //计算辅数量可用量
                // 判断输入的锁定量（辅数量）是否大于当前可用量
                if (wmsRepertory.getLockQuantitySub().compareTo(byId.getUsableQuantitySub()) == DEL_FLAG_1) {
                    throw new JeecgBootException("锁库量(辅数量)不能大于当前可用量!");
                }
                if (wmsRepertory.getLockQuantitySub().compareTo(BigDecimal.ZERO) > 0) {
                    if (ObjectUtil.isNull(byId.getUsableQuantitySub())) {
                        byId.setUsableQuantitySub(BigDecimal.ZERO);
                    }
                    if (ObjectUtil.isNull(byId.getLockQuantitySub())) {
                        byId.setLockQuantitySub(BigDecimal.ZERO);
                    }
                    // 计算当前可用量（辅数量）并重新赋值(当前可用量为: 可用量减去锁定量)
                    byId.setUsableQuantitySub(byId.getUsableQuantitySub().subtract(wmsRepertory.getLockQuantitySub()));
                    // 计算锁定量（辅数量）并重新赋值(当前锁定量为: 传入锁定量加原库存锁定量)
                    byId.setLockQuantitySub(byId.getLockQuantitySub().add(wmsRepertory.getLockQuantitySub()));
                }
            }
            // 修改可用量和锁定量
            this.updateById(byId);
        }
    }

    @Override
    public List<RepertoryAreaVO> getAreaById(String id) {
        WmsRepertory wmsRepertory = this.getById(id);

        LambdaQueryWrapper<WmsRepertory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmsRepertory::getMaterialCode, wmsRepertory.getMaterialCode())
                .eq(WmsRepertory::getWmsBasicWarehouseId, wmsRepertory.getWmsBasicWarehouseId());
        if (StringUtils.isNotBlank(wmsRepertory.getBatchCode())) {
            queryWrapper.eq(WmsRepertory::getBatchCode, wmsRepertory.getBatchCode());
        }
        List<WmsRepertory> repertories = this.list(queryWrapper);

        Map<String, List<WmsRepertory>> collect = repertories.stream().collect(Collectors.groupingBy(WmsRepertory::getWmsBasicWarehouseAreaId));

        List<WmsRepertory> wmsRepertories = collect.values().stream().map(list -> {
            // 计算库存量和可用量
            BigDecimal stockQuantity = list.stream()
                    .filter(o -> ObjectUtil.isNotNull(o.getStockQuantity()))
                    .map(WmsRepertory::getStockQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal usableQuantity = list.stream()
                    .filter(o -> ObjectUtil.isNotNull(o.getUsableQuantity()))
                    .map(WmsRepertory::getUsableQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal lockQuantity = list.stream()
                    .filter(o -> ObjectUtil.isNotNull(o.getLockQuantity()))
                    .map(WmsRepertory::getLockQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 获取分组中的第一个WmsRepertory对象
            WmsRepertory repertory = list.get(0);
            // 设置库存量和可用量
            repertory.setStockQuantity(stockQuantity);
            repertory.setUsableQuantity(usableQuantity.subtract(lockQuantity));

            return repertory;
        }).collect(Collectors.toList());

        wmsRepertories.forEach(w -> {
            if (StringUtils.isNotBlank(w.getWmsBasicWarehouseAreaLocationId())) {
                extracted(w);
            }
        });

        List<RepertoryAreaVO> repertoryAreaVOS = BeanUtil.copyToList(wmsRepertories, RepertoryAreaVO.class);
        List<String> repertoryIds = repertoryAreaVOS.stream().map(RepertoryAreaVO::getWmsBasicWarehouseAreaId).collect(Collectors.toList());
        Map<String, WmsBasicWarehouseArea> areaMap = warehouseAreaService.listByIds(repertoryIds).stream()
                .collect(Collectors.toMap(WmsBasicWarehouseArea::getId, Function.identity()));

        repertoryAreaVOS.forEach(r -> {
            WmsBasicWarehouseArea area = areaMap.get(r.getWmsBasicWarehouseAreaId());
            if (ObjectUtil.isNotNull(area)) {
                r.setAreaName(area.getName());
            }
        });

        return repertoryAreaVOS.stream().map(repertory -> {
            repertory.setLocationTag(StringUtils.isNotBlank(repertory.getWmsBasicWarehouseAreaLocationId()));
            return repertory;
        }).collect(Collectors.toList());
    }

    @Override
    public List<RepertoryLocationVO> getLocationById(String id) {
        WmsRepertory wmsRepertory = this.getById(id);

        LambdaQueryWrapper<WmsRepertory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmsRepertory::getMaterialCode, wmsRepertory.getMaterialCode())
                .eq(WmsRepertory::getWmsBasicWarehouseId, wmsRepertory.getWmsBasicWarehouseId())
                .eq(WmsRepertory::getWmsBasicWarehouseAreaId, wmsRepertory.getWmsBasicWarehouseAreaId());
        if (StringUtils.isNotBlank(wmsRepertory.getBatchCode())) {
            queryWrapper.eq(WmsRepertory::getBatchCode, wmsRepertory.getBatchCode());
        }
        List<WmsRepertory> repertories = this.list(queryWrapper);

        List<RepertoryLocationVO> repertoryAreaVOS = BeanUtil.copyToList(repertories, RepertoryLocationVO.class);
        List<String> repertoryIds = repertoryAreaVOS.stream().map(RepertoryLocationVO::getWmsBasicWarehouseAreaLocationId).collect(Collectors.toList());
        Map<String, WmsBasicWarehouseAreaLocation> locationMap = warehouseAreaLocationService.listByIds(repertoryIds)
                .stream().collect(Collectors.toMap(WmsBasicWarehouseAreaLocation::getId, Function.identity()));

        repertoryAreaVOS.forEach(r -> {
            WmsBasicWarehouseAreaLocation location = locationMap.get(r.getWmsBasicWarehouseAreaLocationId());
            if (ObjectUtil.isNotNull(location)) {
                r.setLocationName(location.getName());
            }
        });

        return repertoryAreaVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void unlock(WmsRepertory wmsRepertory) {
        // 获取当前登录用户
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 创建对象并赋值
        WmsRepertoryLockHistory wmsRepertoryLockHistory = new WmsRepertoryLockHistory();
        wmsRepertoryLockHistory.setLockType("1");
        wmsRepertoryLockHistory.setOperationType("2");
        wmsRepertoryLockHistory.setOperator(user.getUsername());
        wmsRepertoryLockHistory.setOperatorDate(new Date());
        wmsRepertoryLockHistory.setWmsRepertoryId(wmsRepertory.getId());
        wmsRepertoryLockHistory.setRemark(wmsRepertory.getRemark());
        wmsRepertoryLockHistory.setLockQuantityMain(wmsRepertory.getUnlockNumber());
        wmsRepertoryLockHistory.setLockQuantitySub(wmsRepertory.getUnlockNumberSub());
        // 添加一条解库日志
        wmsRepertoryLockHistoryService.save(wmsRepertoryLockHistory);
        WmsRepertory byId = this.getById(wmsRepertory.getId());
        if (ObjectUtil.isNotNull(wmsRepertory.getUnlockNumber())) {
            if (wmsRepertory.getUnlockNumber().compareTo(BigDecimal.ZERO) > 0) {
                // 判断输入的解库量是否大于锁库量
                int i = wmsRepertory.getUnlockNumber().compareTo(wmsRepertory.getLockQuantity());
                if (i == 1) {
                    throw new JeecgBootException("解库量不能大于当前锁库量!");
                }
                // 计算当前锁定量并重新赋值(当前锁定量为: 锁定量减去解锁量)
                byId.setLockQuantity(byId.getLockQuantity().subtract(wmsRepertory.getUnlockNumber()));
                // 计算当前可用量并重新赋值(当前可用量为: 可用量加上解锁量)
                byId.setUsableQuantity(byId.getUsableQuantity().add(wmsRepertory.getUnlockNumber()));
                // 计算库存状态
                if (i == 0) {
                    byId.setStatus(NORMAL);
                }
            }
        }
        if (ObjectUtil.isNotNull(wmsRepertory.getUnlockNumberSub())) {
            if (wmsRepertory.getUnlockNumberSub().compareTo(BigDecimal.ZERO) > 0) {
                // 判断输入的解库量是否大于锁库量
                int i = wmsRepertory.getUnlockNumberSub().compareTo(wmsRepertory.getLockQuantitySub());
                if (i == 1) {
                    throw new JeecgBootException("解库量(辅数量)不能大于当前锁库量(辅数量)!");
                }
                // 计算当前锁定量并重新赋值(当前锁定量为: 锁定量减去解锁量)
                byId.setLockQuantitySub(byId.getLockQuantitySub().subtract(wmsRepertory.getUnlockNumberSub()));
                // 计算当前可用量并重新赋值(当前可用量为: 可用量加上解锁量)
                byId.setUsableQuantitySub(byId.getUsableQuantitySub().add(wmsRepertory.getUnlockNumberSub()));
            }
        }
        // 修改可用量和锁定量
        this.updateById(byId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void freeze(WmsRepertoryFreezeHistory wmsRepertoryFreezeHistory) {
        // 根据传入的ID查询该物料的状态
        WmsRepertory repertory = this.getById(wmsRepertoryFreezeHistory.getWmsRepertoryId());
        // 如果该物料已经被冻结过则进行提示
        if ("freeze".equals(repertory.getStatus())) {
            throw new JeecgBootException("该物料已经冻结过!");
        }
        repertory.setStatus(FREEZE);
        // 修改该物料状态为冻结
        this.updateById(repertory);
        // 获取当前登录用户
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 添加一条冻结日志
        WmsRepertoryFreezeHistory repertoryFreezeHistory = new WmsRepertoryFreezeHistory();
        repertoryFreezeHistory.setWmsRepertoryId(wmsRepertoryFreezeHistory.getWmsRepertoryId());
        repertoryFreezeHistory.setOperator(user.getUsername());
        repertoryFreezeHistory.setOperatorDate(new Date());
        repertoryFreezeHistory.setOperationType(wmsRepertoryFreezeHistory.getOperationType());
        repertoryFreezeHistory.setCause(wmsRepertoryFreezeHistory.getCause());
        wmsRepertoryFreezeHistoryService.save(repertoryFreezeHistory);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void unfreeze(WmsRepertoryFreezeHistory wmsRepertoryFreezeHistory) {
        // 根据传入的ID查询该物料的状态
        WmsRepertory repertory = this.getById(wmsRepertoryFreezeHistory.getWmsRepertoryId());
        // 如果该物料已经被冻结过则进行提示
        if (NORMAL.equals(repertory.getStatus())) {
            throw new JeecgBootException("该物料还未冻结!");
        }
        repertory.setStatus(NORMAL);
        // 修改该物料状态为解冻
        this.updateById(repertory);
        //记录解冻日志
        //获取当前登录用户
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        wmsRepertoryFreezeHistory.setOperator(user.getUsername());
        wmsRepertoryFreezeHistory.setOperatorDate(new Date());
        wmsRepertoryFreezeHistoryService.save(wmsRepertoryFreezeHistory);
    }

    @Override
    public org.jeecg.modules.business.repertory.entity.vo.RepertoryVO queryById(String id) {
        WmsRepertory repertory = this.getById(id);
        org.jeecg.modules.business.repertory.entity.vo.RepertoryVO repertoryVO = cn.hutool.core.bean.BeanUtil.copyProperties(repertory, org.jeecg.modules.business.repertory.entity.vo.RepertoryVO.class);
        WmsBasicWarehouse warehouse = warehouseService.getById(repertoryVO.getWmsBasicWarehouseId());
        WmsBasicWarehouseArea warehouseArea = warehouseAreaService.getById(repertoryVO.getWmsBasicWarehouseAreaId());
        WmsBasicWarehouseAreaLocation warehouseAreaLocation = warehouseAreaLocationService.getById(repertoryVO.getWmsBasicWarehouseAreaLocationId());
        BasicUnit unit = unitService.getById(repertoryVO.getWmsBasicUnitId());
        repertoryVO.setWarehouseName(warehouse.getName());
        if (ObjectUtil.isNotNull(warehouseArea) && StringUtils.isNotBlank(warehouseArea.getName())) {
            repertoryVO.setAreaName(warehouseArea.getName());
        }
        if (ObjectUtil.isNotNull(warehouseAreaLocation) && StringUtils.isNotBlank(warehouseAreaLocation.getName())) {
            repertoryVO.setLocationName(warehouseAreaLocation.getName());
        }
        if (ObjectUtil.isNotNull(unit) && StringUtils.isNotBlank(unit.getName())) {
            repertoryVO.setUnitName(unit.getName());
        }
        if (StringUtils.isNotBlank(repertory.getUnitSub())) {
            BasicUnit unitSub = unitService.getById(repertory.getUnitSub());
            if (ObjectUtil.isNotNull(unitSub)) {
                repertoryVO.setUnitSub(unitSub.getName());
            }
        }
        return repertoryVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(RepertoryDocumentVO repertoryDocumentVOS) {
        log.info("入库单增加库存开始.....");
        // 初始化三个列表，用于存储待添加、更新和删除的 WmsRepertory 对象
        ArrayList<WmsRepertory> wmsRepertory = new ArrayList<>();
        ArrayList<WmsRepertory> update = new ArrayList<>();
        ArrayList<WmsRepertory> delete = new ArrayList<>();
        // 从传入的 repertoryDocumentVOS 中提取物料编号列表
        List<String> materialIds = repertoryDocumentVOS.getRepertoryVOS().stream()
                .map(RepertoryVO::getWmsBasicMaterialId)
                .collect(Collectors.toList());
        // 使用物料编号列表获取物料信息，并转化为 Map
        Map<String, BasicMaterial> materialMap = materialService.listByIds(materialIds).stream()
                .collect(Collectors.toMap(BasicMaterial::getId, material -> material));
        // 初始化入库单和入库单物料映射
        WmsInReceipt inReceipt = new WmsInReceipt();
        Map<String, WmsInReceiptMaterial> receiptMaterialMap = new HashMap<>();
        List<String> materialIdList = new ArrayList<>();
        // 如果单据类型为 1（入库单），则获取相应的入库单和物料信息
        List<String> basicMaterialList = new ArrayList<>();
        if (repertoryDocumentVOS.getDocumentType() == 1) {
            inReceipt = inReceiptService.getById(repertoryDocumentVOS.getInvoicesId());
            if (ObjectUtil.isNotNull(inReceipt)) {
                //部分入库流程不需要记录库存
                if (ArrayUtil.contains(noUpdateStock, inReceipt.getDocumentType())) {
                    return;
                }
            }
            List<WmsInReceiptMaterial> inReceiptMaterials = inReceiptMaterialService.selectByMainId(repertoryDocumentVOS.getInvoicesId());
            receiptMaterialMap = inReceiptMaterials
                    .stream().collect(Collectors.toMap(WmsInReceiptMaterial::getId, Function.identity()));
            materialIdList = inReceiptMaterials
                    .stream().map(WmsInReceiptMaterial::getId).collect(Collectors.toList());
            basicMaterialList = inReceiptMaterials.stream().map(WmsInReceiptMaterial::getWmsBasicMaterialId).distinct().collect(Collectors.toList());
        }
        //物料-同批次号入库方式map
        Map<String, String> materialControlMap = getMaterialType(basicMaterialList);
        // 初始化移库单和移库单物料映射
        WmsMoveReceipt moveReceipt = new WmsMoveReceipt();
        Map<String, WmsMoveReceiptMaterial> moveReceiptMaterialMap = new HashMap<>();
        // 如果单据类型为 3（移库单），则获取相应的移库单和物料信息
        if (repertoryDocumentVOS.getDocumentType() == 3) {
            moveReceipt = moveReceiptService.getById(repertoryDocumentVOS.getInvoicesId());
            moveReceiptMaterialMap = moveReceiptMaterialService
                    .selectByMainId(repertoryDocumentVOS.getInvoicesId())
                    .stream().collect(Collectors.toMap(WmsMoveReceiptMaterial::getId, Function.identity()));
            materialIdList = moveReceiptMaterialService
                    .selectByMainId(repertoryDocumentVOS.getInvoicesId())
                    .stream().map(WmsMoveReceiptMaterial::getId).collect(Collectors.toList());
        }
        // 提升作用域
        WmsInReceipt finalInReceipt = inReceipt;
        Map<String, WmsInReceiptMaterial> finalReceiptMaterialMap = receiptMaterialMap;
        List<String> finalMaterialIdList = materialIdList;
        WmsMoveReceipt finalMoveReceipt = moveReceipt;
        Map<String, WmsMoveReceiptMaterial> finalMoveReceiptMaterialMap = moveReceiptMaterialMap;
        // 逐个处理库存信息
        repertoryDocumentVOS.getRepertoryVOS().forEach(r -> {
            // 获取物料信息
            BasicMaterial material = materialMap.get(r.getWmsBasicMaterialId());
            // 初始化一些变量
            String organization = null;
            String ownerType = null;
            String owner = null;
            String remark = null;
            // 处理入库单信息
            if (ObjectUtil.isNotNull(finalInReceipt) && CollectionUtil.isNotEmpty(finalReceiptMaterialMap)) {
                organization = finalInReceipt.getOrganization();
                ownerType = finalInReceipt.getOwnerType();
                owner = finalInReceipt.getOwner();
                remark = finalInReceipt.getRemark();
                r.setSupplier(finalInReceipt.getSupplier());
                String code = null;
                // 根据货主类型和货主名称查询货主编码
                if (StringUtils.isNotBlank(ownerType) && StringUtils.isNotBlank(owner)) {
                    code = extracted(ownerType, owner);
                }
                // 在入库单物料映射中查找匹配的物料
                WmsInReceiptMaterial inReceiptMaterial = null;
                ArrayList<String> strings = new ArrayList<>();
                for (String finalMaterialId : finalMaterialIdList) {
                    inReceiptMaterial = finalReceiptMaterialMap.get(finalMaterialId);
                    strings.add(finalMaterialId);
                    break;
                }
                finalMaterialIdList.removeAll(strings);
                // 如果找到匹配的入库单物料，则创建相应的库存对象并添加到列表
                if (ObjectUtil.isNotNull(inReceiptMaterial)) {
                    WmsRepertory repertory = inReceipt(organization, ownerType, owner, remark, inReceiptMaterial, r, material, code);
                    repertory.setStackNumber(repertoryDocumentVOS.getStackNumber());
                    wmsRepertory.add(repertory);
                }
            }
            // 处理移库单信息
            if (ObjectUtil.isNotNull(finalMoveReceipt) && CollectionUtil.isNotEmpty(finalMoveReceiptMaterialMap)) {
                organization = finalMoveReceipt.getOrganization();
                ownerType = finalMoveReceipt.getOwnerType();
                owner = finalMoveReceipt.getTransferFromOwner();
                remark = finalMoveReceipt.getRemark();
                // 根据货主类型和货主名称查询货主编码
                String code = null;
                if (StringUtils.isNotBlank(ownerType) && StringUtils.isNotBlank(owner)) {
                    code = extracted(ownerType, owner);
                }
                String warehouseId = finalMoveReceipt.getTransferFromWarehouseId();
                // 在移库单物料映射中查找匹配的物料
                WmsMoveReceiptMaterial wmsMoveReceiptMaterial = null;
                ArrayList<String> strings = new ArrayList<>();
                for (String finalMaterialId : finalMaterialIdList) {
                    wmsMoveReceiptMaterial = finalMoveReceiptMaterialMap.get(finalMaterialId);
                    strings.add(finalMaterialId);
                    break;
                }
                finalMaterialIdList.removeAll(strings);
                // 如果找到匹配的移库单物料，则创建相应的库存对象并添加到列表
                if (ObjectUtil.isNotNull(wmsMoveReceiptMaterial)) {
                    WmsRepertory repertory = moveReceipt(organization, ownerType, owner, remark, wmsMoveReceiptMaterial, r, material, warehouseId, code);
                    wmsRepertory.add(repertory);
                }
            }
        });
        // 拿取所有库存信息
        List<WmsRepertory> list = this.list(new LambdaQueryWrapper<WmsRepertory>()
                .isNotNull(WmsRepertory::getWmsBasicWarehouseId)
                .isNotNull(WmsRepertory::getMaterialId)
        );
        // 遍历待添加的库存对象，检查是否已存在，进行更新或添加操作
        List<WmsRepertory> needDelete = new ArrayList<>();
        wmsRepertory.forEach(w -> {
            //如果同批次号校验是禁止入库,说明为不可叠的情况
            //校验库存中是否有同物料编码同批次号的物料，如果有，不报错，更新此物料的仓库信息、最新入库时间和更新人更新时间,重量使用最新的库存信息
            if (Objects.equals(materialControlMap.get(w.getMaterialId()),"3")){
                //如果批次号+物料编码有多个,则就只保留一个
                List<WmsRepertory> repertory2 = findExistingRepertory2(list, w);
                if (CollectionUtil.isNotEmpty(repertory2)){
                    WmsRepertory repertory = repertory2.get(0);
                    validateAndUpdate2(repertory, w);
                    update.add(repertory);
                    delete.add(w);
                    for (int i = 1; i < repertory2.size(); i++) {
                        needDelete.add(repertory2.get(i));
                    }
                }
            }else {
                WmsRepertory repertory = findExistingRepertory(list, w);
                if (repertory != null) {
                    validateAndUpdate(repertory, w);
                    update.add(repertory);
                    delete.add(w);
                }
            }
        });
        // 移除需要删除的库存对象
        wmsRepertory.removeAll(delete);
        // 保存新增的库存对象
        if (CollectionUtil.isNotEmpty(wmsRepertory)) {
            // 分组
            List<WmsRepertory> wmsRepertories = extracted(wmsRepertory);
            if (repertoryDocumentVOS.getDocumentType() != 3) {
                wmsRepertories.forEach(one -> {
                    one.setWmsBasicSupplierId(repertoryDocumentVOS.getWmsBasicSupplierId());
                });
            }
            this.saveBatch(wmsRepertories);
        }
        // 批量更新库存对象
        if (CollectionUtil.isNotEmpty(update)) {
            update.forEach(one -> {
                one.setWmsBasicSupplierId(repertoryDocumentVOS.getWmsBasicSupplierId());
            });
            this.updateBatchById(update);
        }
        // 删除重复数据
        if (CollectionUtil.isNotEmpty(needDelete)) {
            this.removeBatchByIds(needDelete);
        }
        log.info("入库单增加库存结束.....");
    }
    //物料id-物料控制方式map
    Map<String, String> getMaterialType(List<String> materialIdList){
        Map<String, String> map = new HashMap<>();
        if (CollectionUtil.isEmpty(materialIdList)){
            return map;
        }
        List<String> collect = materialIdList.stream().distinct().collect(Collectors.toList());
        List<MaterialInfoVO> materialInfoList = wmsValidMapper.selectInboundControlType(collect);
        map = materialInfoList.stream().filter(s->ObjectUtil.isNotNull(s.getInboundControlType())).collect(Collectors.toMap(MaterialInfoVO::getWmsBasicMaterialId, MaterialInfoVO::getInboundControlType));
        return map;
    }

    /**
     * 根据货主类型和货主名称查询货主编码
     *
     * @param ownerType
     * @param owner
     * @return java.lang.String
     * @author hansen
     * @since 2023/8/31 13:07
     */
    private String extracted(String ownerType, String owner) {
        String code = null;
        if (ownerType.equals(SUPPLIER)) {
            BasicSupplier supplier = supplierService.getOne(new LambdaQueryWrapper<BasicSupplier>()
                    .eq(BasicSupplier::getCode, owner));
            if (ObjectUtil.isNotNull(supplier)) {
                code = supplier.getCode();
            }
        }
        if (ownerType.equals(ORGANIZATION)) {
            List<SysDepartModel> allSysDepart = sysBaseAPI.getAllSysDepart();
            SysDepartModel sysDepartModel = allSysDepart.stream().filter(a -> a.getDepartName().equals(owner)).findAny().orElse(null);
            if (sysDepartModel != null) {
                code = sysDepartModel.getOrgCode();
            }
        }
        if (ownerType.equals(CLIENT)) {
            BasicCustomer customer = customerService.getOne(new LambdaQueryWrapper<BasicCustomer>()
                    .eq(BasicCustomer::getCode, owner));
            if (ObjectUtil.isNotNull(customer)) {
                code = customer.getCode();
            }
        }
        return code;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reduce(RepertoryDocumentVO repertoryDocumentVOS) {
        // 声明变量
        ArrayList<WmsRepertory> updateRepertoryList = new ArrayList<>();
        ArrayList<WmsRepertory> deleteRepertoryList = new ArrayList<>();
        // 根据单据类型获取对应的单据信息
        WmsMoveReceipt moveReceipt = new WmsMoveReceipt();
        WmsOutReceipt outReceipt = new WmsOutReceipt();
        if (repertoryDocumentVOS.getDocumentType() == 3) {
            moveReceipt = moveReceiptService.getById(repertoryDocumentVOS.getInvoicesId());
        } else if (repertoryDocumentVOS.getDocumentType() == 2) {
            outReceipt = outReceiptService.getById(repertoryDocumentVOS.getInvoicesId());
            if (ObjectUtil.isNotNull(outReceipt)) {
                //部分出库流程不需要记录库存
                if (ArrayUtil.contains(noUpdateStock, outReceipt.getDocumentType())) {
                    return;
                }
            }
        }
        WmsMoveReceipt finalMoveReceipt = moveReceipt;
        WmsOutReceipt finalOutReceipt = outReceipt;
        // 遍历传进来的出库单明细
        repertoryDocumentVOS.getRepertoryVOS().forEach(r -> {
            // 构建查询条件
            LambdaQueryWrapper<WmsRepertory> queryWrapper = new LambdaQueryWrapper<>();
            if (finalMoveReceipt.getId() != null) {
                queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseId, finalMoveReceipt.getTransferFromWarehouseId());
                queryWrapper.eq(StringUtils.isNotBlank(r.getWmsBasicWarehouseAreaId()), WmsRepertory::getWmsBasicWarehouseAreaId, r.getWmsBasicWarehouseAreaId());
                queryWrapper.eq(StringUtils.isNotBlank(r.getWmsBasicWarehouseAreaLocationId()), WmsRepertory::getWmsBasicWarehouseAreaLocationId, r.getWmsBasicWarehouseAreaLocationId());
            } else if (finalOutReceipt.getId() != null) {
                queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseId, r.getWmsBasicWarehouseId());
                if (StringUtils.isNotBlank(r.getWmsBasicWarehouseAreaId())) {
                    queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseAreaId, r.getWmsBasicWarehouseAreaId());
                }
            }
            if (!StrUtil.isEmpty(r.getBatchCode())) {
                queryWrapper.eq(WmsRepertory::getBatchCode, r.getBatchCode());
            } else {
                queryWrapper.eq(WmsRepertory::getMaterialId, r.getWmsBasicMaterialId());
            }
            queryWrapper.last("LIMIT 1");
            // 查询库存
            WmsRepertory repertory = this.getOne(queryWrapper);
            if (Objects.isNull(repertory)) {
                throw new JeecgBootException("当前物料无库存");
            }
            if (FREEZE.equals(repertory.getStatus())) {
                throw new JeecgBootException("物料:" + repertory.getMaterialName() + "批次号:" + repertory.getBatchCode() + "在即时库存的库存状态为已冻结, 不可出库!");
            }
            // 如果出库数量等于现有库存,则标记删除
            if (repertory.getStockQuantity().compareTo(r.getStockQuantity()) == 0) {
                repertory.setDelFlag(1);
                deleteRepertoryList.add(repertory);
            }
            // 移库校验库存量
            BigDecimal sub = NumberUtil.sub(repertory.getStockQuantity(), r.getStockQuantity());
            if (repertoryDocumentVOS.getDocumentType() == 3 && sub.compareTo(new BigDecimal("0")) == -1) {
                throw new JeecgBootException(repertory.getBatchCode() + repertory.getMaterialName() + "物料的移库量不能大于当前可用量, 当前可用量为: " + repertory.getUsableQuantity());
            }
            // 计算库存量
            repertory.setStockQuantity(NumberUtil.sub(repertory.getStockQuantity(), r.getStockQuantity()));
            // 计算可用量
            repertory.setUsableQuantity(NumberUtil.sub(repertory.getStockQuantity(), repertory.getLockQuantity()));
            // 计算辅单位
            if (!StrUtil.isEmpty(repertory.getUnitSub())
                    && !Objects.isNull(repertory.getStockQuantitySub())
                    && !Objects.isNull(r.getStockQuantitySub())) {

                repertory.setStockQuantitySub(NumberUtil.sub(repertory.getStockQuantitySub(), r.getStockQuantitySub()));
                repertory.setUsableQuantitySub(NumberUtil.sub(repertory.getStockQuantitySub(), repertory.getLockQuantitySub()));
            }
            updateRepertoryList.add(repertory);
        });
        // 批量删除标记删除的库存
        if (CollectionUtil.isNotEmpty(deleteRepertoryList)) {
            this.removeBatchByIds(deleteRepertoryList);
        }
        // 批量更新计算后的库存
        if (CollectionUtil.isNotEmpty(updateRepertoryList)) {
            this.updateBatchById(updateRepertoryList);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addInTransitRepertory(RepertoryDocumentVO repertoryDocumentVOS, String deliveryTaskId) {
        List<WmsInTransitRepertory> saveList = new ArrayList<>();
        WmsDeliveryTask deliveryTask = deliveryTaskService.getById(deliveryTaskId);
        if (Objects.isNull(deliveryTask)) {
            return;
        }
        // 遍历传进来的仓库出库单明细
        repertoryDocumentVOS.getRepertoryVOS().forEach(r -> {
            // 构建查询条件
            LambdaQueryWrapper<WmsRepertory> queryWrapper = new LambdaQueryWrapper<>();
            if (StrUtil.isNotBlank(r.getWmsBasicWarehouseId())) {
                queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseId, r.getWmsBasicWarehouseId());
            }
            if (StrUtil.isNotBlank(r.getBatchCode())) {
                queryWrapper.eq(WmsRepertory::getBatchCode, r.getBatchCode());
            } else if (StrUtil.isNotBlank(r.getWmsBasicMaterialId())) {
                queryWrapper.eq(WmsRepertory::getMaterialId, r.getWmsBasicMaterialId());
            } else {
                return;
            }
            queryWrapper.last("LIMIT 1");
            // 查询库存
            WmsRepertory repertory = this.getOne(queryWrapper);
            if (Objects.isNull(repertory)) {
                return;
            }
            if (FREEZE.equals(repertory.getStatus())) {
                throw new JeecgBootException("物料:" + repertory.getMaterialName() + "批次号:" + repertory.getBatchCode() + "在即时库存的库存状态为已冻结, 不可出库!");
            }
            WmsInTransitRepertory wmsInTransitRepertory = cn.hutool.core.bean.BeanUtil.toBean(repertory, WmsInTransitRepertory.class);
            wmsInTransitRepertory.setId(null);
            wmsInTransitRepertory.setRepertoryId(r.getId());
            wmsInTransitRepertory.setStockQuantity(r.getStockQuantity());
            wmsInTransitRepertory.setUsableQuantity(r.getUsableQuantity());
            wmsInTransitRepertory.setStatus("InTransit");
            wmsInTransitRepertory.setDeliveryTaskId(deliveryTaskId);
            if ("调入方".equals(deliveryTask.getInTransitOwnership())) {
                wmsInTransitRepertory.setWmsBasicWarehouseId(deliveryTask.getInWarehouseId());
            } else if ("调出方".equals(deliveryTask.getInTransitOwnership())) {
                wmsInTransitRepertory.setWmsBasicWarehouseId(deliveryTask.getOutWarehouseId());
            }
            wmsInTransitRepertory.setWmsBasicWarehouseAreaId(null);
            wmsInTransitRepertory.setWmsBasicWarehouseAreaLocationId(null);
            saveList.add(wmsInTransitRepertory);
        });
        inTransitRepertoryService.saveBatch(saveList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteInTransitRepertory(RepertoryDocumentVO repertoryDocumentVOS, String deliveryTaskId) {
        repertoryDocumentVOS.getRepertoryVOS().forEach(r -> {
            LambdaQueryWrapper<WmsInTransitRepertory> queryWrapper = new LambdaQueryWrapper<WmsInTransitRepertory>()
                    .eq(WmsInTransitRepertory::getDeliveryTaskId, deliveryTaskId);
            if (StringUtils.isNotBlank(r.getBatchCode())) {
                queryWrapper.eq(WmsInTransitRepertory::getBatchCode, r.getBatchCode());
                inTransitRepertoryService.remove(queryWrapper);
            } else if (StringUtils.isNotBlank(r.getWmsBasicMaterialId())) {
                queryWrapper.eq(WmsInTransitRepertory::getMaterialId, r.getWmsBasicMaterialId());
                inTransitRepertoryService.remove(queryWrapper);
            } else {
                return;
            }
        });
    }

    @Override
    public void outSubmit(String id, boolean checkStock) {

        if (!checkStock) {
            return;
        }
        // 根据出库单ID查询出库单信息
        WmsOutReceipt outReceipt = outReceiptService.getById(id);
        // 根据出库单id查询出库单物料列表
        List<WmsOutReceiptMaterial> receiptMaterialList = outReceiptMaterialService.list(new LambdaQueryWrapper<WmsOutReceiptMaterial>()
                .eq(WmsOutReceiptMaterial::getWmsOutReceiptId, id));
        if (CollectionUtil.isEmpty(receiptMaterialList)) {
            return;
        }
        for (WmsOutReceiptMaterial receiptMaterial : receiptMaterialList) {
            // 查询条件
            LambdaQueryWrapper<WmsRepertory> queryWrapper = new LambdaQueryWrapper<>();
            if (!StrUtil.isEmpty(receiptMaterial.getWmsBasicWarehouseId())) {
                queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseId, receiptMaterial.getWmsBasicWarehouseId());
            }
            queryWrapper.eq(StrUtil.isNotBlank(receiptMaterial.getWmsBasicWarehouseAreaId()), WmsRepertory::getWmsBasicWarehouseAreaId, receiptMaterial.getWmsBasicWarehouseAreaId());
            if (!StrUtil.isEmpty(receiptMaterial.getBatchCode())) {
                queryWrapper.eq(WmsRepertory::getBatchCode, receiptMaterial.getBatchCode());
            } else {
                queryWrapper.eq(WmsRepertory::getMaterialId, receiptMaterial.getWmsBasicMaterialId());
            }
            queryWrapper.last("LIMIT 1");
            WmsRepertory realRepertory = wmsRepertoryMapper.selectOne(queryWrapper);
            //查询物料名称
            BasicMaterial basicMaterial = materialService.getById(receiptMaterial.getWmsBasicMaterialId());
            if (Objects.isNull(realRepertory)) {
                WmsBasicWarehouse warehouse = warehouseService.getById(receiptMaterial.getWmsBasicWarehouseId());
                String warehouseName = Objects.isNull(warehouse) ? "" : warehouse.getName();
                String errorMessage = warehouseName + "仓库下查询不到批号,找不到物料";
                if (!StrUtil.isEmpty(receiptMaterial.getBatchCode())) {
                    errorMessage += ",批次号为" + receiptMaterial.getBatchCode();
                } else {
                    if (!Objects.isNull(basicMaterial)) {
                        errorMessage += ",物料是" + basicMaterial.getName();
                    } else {
                        errorMessage += ",物料号为" + receiptMaterial.getMaterialCode();
                    }
                }
                throw new JeecgBootException(errorMessage);
            } else {

                // 比较出库量和当前可用量
                int i = ObjectUtil.compare(realRepertory.getUsableQuantity(), receiptMaterial.getOutboundQuantity());
                // 如果出库量大于可用量,抛出异常
                if (-1 == i) {
                    if (!Objects.isNull(basicMaterial)) {
                        String materialName = basicMaterial.getName();
                        if (!StrUtil.isEmpty(receiptMaterial.getBatchCode())) {
                            materialName += (",批次号为" + receiptMaterial.getBatchCode());
                        }
                        throw new JeecgBootException(materialName + "的出库量不能大于当前可用量, 当前可用量为: " + NumberUtil.roundDown(realRepertory.getUsableQuantity(), 2));
                    } else {
                        String materialName = receiptMaterial.getMaterialCode();
                        if (!StrUtil.isEmpty(receiptMaterial.getBatchCode())) {
                            materialName += (",批次号为" + receiptMaterial.getBatchCode());
                        }
                        throw new JeecgBootException(materialName + "的出库量不能大于当前可用量, 当前可用量为: " + NumberUtil.roundDown(realRepertory.getUsableQuantity(), 2));
                    }
                }
                if (realRepertory.getStatus().equals("freeze")) {
                    if (!Objects.isNull(basicMaterial)) {
                        throw new JeecgBootException(basicMaterial.getName() + "被冻结，无法出库");
                    } else {
                        throw new JeecgBootException(receiptMaterial.getMaterialCode() + "被冻结，无法出库");
                    }
                }
            }

        }
        //校验出库单数量是否超过出库任务数量
        commonOutboundUtil.checkOrderQuantity(outReceipt);
    }

    /**
     * 获取仓库, 库区, 库位信息
     *
     * @return org.jeecg.modules.business.repertory.service.impl.WmsRepertoryServiceImpl.Result
     * @author hansen
     * @since 2023/9/8 9:57
     */
    @NotNull
    private Result getResult() {
        Map<String, WmsBasicWarehouse> warehouseMap = warehouseService.list().stream().collect(Collectors.toMap(WmsBasicWarehouse::getId, Function.identity()));
        Map<String, WmsBasicWarehouseArea> areaMap = warehouseAreaService.list().stream().collect(Collectors.toMap(WmsBasicWarehouseArea::getId, Function.identity()));
        Map<String, WmsBasicWarehouseAreaLocation> locationMap = warehouseAreaLocationService.list().stream().collect(Collectors.toMap(WmsBasicWarehouseAreaLocation::getId, Function.identity()));
        Result result = new Result(warehouseMap, areaMap, locationMap);
        return result;
    }

    @Override
    public void moveSubmit(String id) {
        // 根据移库单ID查询移库单详情
        WmsMoveReceipt byId = moveReceiptService.getById(id);
        if (byId == null) {
            throw new JeecgBootException("移库单不存在！");
        }
        // 获取货主编码
//        String ownerCode = null;
//        if (StringUtils.isNotBlank(byId.getOwnerType()) && StringUtils.isNotBlank(byId.getTransferFromOwner())) {
//            ownerCode = extracted(byId.getOwnerType(), byId.getTransferFromOwner());
//        }
        // 根据移库单id查询移库单物料列表
        List<WmsMoveReceiptMaterial> moveReceiptMaterials = moveReceiptMaterialService.list(new LambdaQueryWrapper<WmsMoveReceiptMaterial>()
                .eq(WmsMoveReceiptMaterial::getWmsMoveReceiptId, id));
        if (CollectionUtil.isEmpty(moveReceiptMaterials)) {
            throw new JeecgBootException("移库单物料为空！");
        }
        // 查询即时库存信息
//        List<WmsRepertory> list = this.list();
        // 提升作用域
//        String finalOwnerCode = ownerCode;
        // 过滤是否有该货主信息
//        WmsRepertory wmsRepertory = list.stream().filter(a -> Objects.equals(a.getOwnerType(), byId.getOwnerType())
//                && Objects.equals(a.getOwnerCode(), finalOwnerCode)
//                && Objects.equals(a.getStockOrg(), byId.getOrganization())).findFirst().orElse(null);
//        if (ObjectUtil.isNull(wmsRepertory)) {
//            throw new JeecgBootException("即时库存中没有货主: " + byId.getTransferFromOwner() + "存入的物料!");
//        }
        // 查询仓库, 库区, 库位, 名称并存入map
        Result result = getResult();
        // 按批次号、物料id、仓库id、仓区id、仓位id、货主类型、货主编码、组织分组
        Map<String, List<WmsMoveReceiptMaterial>> collect = moveReceiptMaterials.stream()
                .filter(move ->
//                                ObjectUtil.isNotNull(move.getBatchCode())
//                        && ObjectUtil.isNotNull(byId.getOrganization())
//                        && ObjectUtil.isNotNull(byId.getOwnerType())
//                        && ObjectUtil.isNotNull(finalOwnerCode)
                                ObjectUtil.isNotNull(move.getWmsBasicMaterialId())
                                && ObjectUtil.isNotNull(byId.getTransferFromWarehouseId())
//                        && ObjectUtil.isNotNull(move.getTransferFromAreaId())
//                        && ObjectUtil.isNotNull(move.getTransferFromLocationId())
                )
                .collect(Collectors.groupingBy(move -> move.getBatchCode() + move.getWmsBasicMaterialId()
                                + byId.getTransferFromWarehouseId() + move.getTransferFromAreaId() + move.getTransferFromLocationId()
                        /*+ byId.getOrganization() + byId.getOwnerType() + finalOwnerCode*/));
        // 查询条件
        LambdaQueryWrapper<WmsRepertory> queryWrapper = new LambdaQueryWrapper<>();
        // 遍历移库单物料
        List<WmsMoveReceiptMaterial> materials = moveReceiptMaterials.stream().filter(move ->
//                        ObjectUtil.isNotNull(move.getBatchCode())
                        ObjectUtil.isNotNull(move.getWmsBasicMaterialId())
                        && ObjectUtil.isNotNull(byId.getTransferFromWarehouseId())
//                        && ObjectUtil.isNotNull(move.getTransferFromAreaId())
//                        && ObjectUtil.isNotNull(move.getTransferFromLocationId())
        ).collect(Collectors.toList());
        for (WmsMoveReceiptMaterial move : materials) {
            // 获取同批次号、物料、仓库、区、位、货主类型、货主编码、组织的移库物料
            List<WmsMoveReceiptMaterial> wmsMoveReceiptMaterials = collect.get(move.getBatchCode() + move.getWmsBasicMaterialId()
                            + byId.getTransferFromWarehouseId() + move.getTransferFromAreaId() + move.getTransferFromLocationId()
                    /*+ byId.getOrganization() + byId.getOwnerType() + finalOwnerCode*/);
            // 计算同批次号、物料、仓库、区、位、货主类型、货主编码、组织的移库总量
            BigDecimal usableQuantity = wmsMoveReceiptMaterials.stream()
                    .filter(o -> ObjectUtil.isNotNull(o.getTransferQuantity()))
                    .map(WmsMoveReceiptMaterial::getTransferQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 获取同批次号、物料、仓库、区、位的第一条移库物料
            WmsMoveReceiptMaterial wmsMoveReceiptMaterial = wmsMoveReceiptMaterials.get(0);
            // 查询物料信息
            BasicMaterial material = materialService.getById(wmsMoveReceiptMaterial.getWmsBasicMaterialId());
            if (material == null) {
                throw new JeecgBootException("物料不存在！");
            }
            // 设置查询条件
            queryWrapper.eq(WmsRepertory::getMaterialId, wmsMoveReceiptMaterial.getWmsBasicMaterialId());
            queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseId, byId.getTransferFromWarehouseId());
            if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getBatchCode())) {
                queryWrapper.eq(WmsRepertory::getBatchCode, wmsMoveReceiptMaterial.getBatchCode());
            }
            WmsBasicWarehouseArea wmsBasicWarehouseArea = null;
            if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getTransferFromAreaId())) {
                wmsBasicWarehouseArea = result.areaMap.get(wmsMoveReceiptMaterial.getTransferFromAreaId());
                queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseAreaId, wmsMoveReceiptMaterial.getTransferFromAreaId());
            }
            WmsBasicWarehouseAreaLocation wmsBasicWarehouseAreaLocation = null;
            if (StringUtils.isNotBlank(wmsMoveReceiptMaterial.getTransferFromLocationId())) {
                wmsBasicWarehouseAreaLocation = result.locationMap.get(wmsMoveReceiptMaterial.getTransferFromLocationId());
                queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseAreaLocationId, wmsMoveReceiptMaterial.getTransferFromLocationId());
            }
//                    if (StringUtils.isNotBlank(byId.getOwnerType())) {
//                        queryWrapper.eq(WmsRepertory::getOwnerType, byId.getOwnerType());
//                    }
//                    if (StringUtils.isNotBlank(byId.getOrganization())) {
//                        queryWrapper.eq(WmsRepertory::getStockOrg, byId.getOrganization());
//                    }
//                    if (StringUtils.isNotBlank(finalOwnerCode)) {
//                        queryWrapper.eq(WmsRepertory::getOwnerCode, finalOwnerCode);
//                    }
            queryWrapper.last("LIMIT 1");
            // 查询库存
            WmsRepertory repertory = this.getOne(queryWrapper);
            // 获取仓库, 库区, 库位名称
            WmsBasicWarehouse warehouse = result.warehouseMap.get(byId.getTransferFromWarehouseId());
            if (warehouse == null) {
                throw new JeecgBootException("仓库不存在！");
            }
            // 判断该货主是否在这个位置存入了物料
            if (ObjectUtil.isNull(repertory)) {
//                        if (ObjectUtil.isNotNull(wmsBasicWarehouseArea) && ObjectUtil.isNull(wmsBasicWarehouseAreaLocation)) {
//                            throw new JeecgBootException("货主: " + byId.getTransferFromOwner() + "没有在仓库: " + warehouse.getName() + ", 库区: " + wmsBasicWarehouseArea.getName() + ", 存入批次号: " + wmsMoveReceiptMaterial.getBatchCode() + ", 物料编码: " + material.getCode() + ", 物料名称: " + material.getName() + ", 的物料, 请核实信息后再出库!");
//                        }
//                        if (ObjectUtil.isNotNull(wmsBasicWarehouseArea) && ObjectUtil.isNotNull(wmsBasicWarehouseAreaLocation)) {
//                            throw new JeecgBootException("货主: " + byId.getTransferFromOwner() + "没有在仓库: " + warehouse.getName() + ", 库区: " + wmsBasicWarehouseArea.getName() + ", 库位: " + wmsBasicWarehouseAreaLocation.getName() + ", 存入批次号: " + wmsMoveReceiptMaterial.getBatchCode() + ", 物料编码: " + material.getCode() + ", 物料名称: " + material.getName() + ", 的物料, 请核实信息后再出库!");
//                        }
//                        throw new JeecgBootException("货主: " + byId.getTransferFromOwner() + "没有在仓库: " + warehouse.getName() + ", 存入批次号: " + wmsBasicWarehouseAreaLocation.getName() + ", 物料编码: " + material.getCode() + ", 物料名称: " + material.getName() + ", 的物料, 请核实信息后再出库!");
                throw new JeecgBootException("货主: " + byId.getTransferFromOwner() + "在仓库: " + warehouse.getName() + ", 没有批次号: " + wmsMoveReceiptMaterial.getBatchCode() + ", 物料编码: " + material.getCode() + ", 物料名称: " + material.getName() + ", 的物料, 请核实信息后再出库!");
            }
            // 清空查询条件
            queryWrapper.clear();
            // 比较移库量和当前可用量
            int i = repertory.getUsableQuantity().compareTo(usableQuantity);
            // 如果移库量大于可用量,抛出异常
            if (-1 == i) {
                String batchCodeStr = StringUtils.isNotBlank(move.getBatchCode()) ? "批次号为" + move.getBatchCode() + "的" : "";
                throw new JeecgBootException(batchCodeStr + material.getName() + "物料的移库量不能大于当前可用量, 当前可用量为: " + repertory.getUsableQuantity());
            }
        }
    }

    @Override
    public List<WmsRepertory> inSubmit(String id) {
        // 根据入库单ID查询入库单信息
        WmsInReceipt byId = inReceiptService.getById(id);
        String ownerCode = null;
        // 获取货主编码
        if (StringUtils.isNotBlank(byId.getOwnerType()) && StringUtils.isNotBlank(byId.getOwner())) {
            ownerCode = extracted(byId.getOwnerType(), byId.getOwner());
        }
        // 提升作用域
        String finalOwnerCode = ownerCode;
        // 根据入库单id查询入库单物料列表
        List<WmsInReceiptMaterial> inReceiptMaterials = inReceiptMaterialService.list(new LambdaQueryWrapper<WmsInReceiptMaterial>()
                .eq(WmsInReceiptMaterial::getWmsInReceiptId, id));
        // 查询条件
        LambdaQueryWrapper<WmsRepertory> queryWrapper = new LambdaQueryWrapper<>();
        // 遍历入库单物料
        inReceiptMaterials.stream().filter(in -> ObjectUtil.isNotNull(in.getBatchCode())
                        && ObjectUtil.isNotNull(in.getWmsBasicMaterialId())
                        && ObjectUtil.isNotNull(in.getWmsBasicWarehouseId())
                        && ObjectUtil.isNotNull(in.getWmsBasicWarehouseAreaId())
                        && ObjectUtil.isNotNull(in.getWmsBasicWarehouseAreaLocationId()))
                .forEach(in -> {
                    // 获取同批次号、物料、仓库、区、位的第一条入库物料
                    WmsInReceiptMaterial wmsInReceiptMaterial = inReceiptMaterials.get(0);
                    // 设置查询条件
                    if (StringUtils.isNotBlank(wmsInReceiptMaterial.getBatchCode())) {
                        queryWrapper.eq(WmsRepertory::getBatchCode, wmsInReceiptMaterial.getBatchCode());
                    }
                    queryWrapper.eq(WmsRepertory::getMaterialId, wmsInReceiptMaterial.getWmsBasicMaterialId());
                    queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseId, wmsInReceiptMaterial.getWmsBasicWarehouseId());
                    if (StringUtils.isNotBlank(wmsInReceiptMaterial.getWmsBasicWarehouseAreaId())) {
                        queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseAreaId, wmsInReceiptMaterial.getWmsBasicWarehouseAreaId());
                    }
                    if (StringUtils.isNotBlank(wmsInReceiptMaterial.getWmsBasicWarehouseAreaLocationId())) {
                        queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseAreaLocationId, wmsInReceiptMaterial.getWmsBasicWarehouseAreaLocationId());
                    }
                    if (StringUtils.isNotBlank(byId.getOwnerType())) {
                        queryWrapper.eq(WmsRepertory::getOwnerType, byId.getOwnerType());
                    }
                    if (StringUtils.isNotBlank(byId.getOrganization())) {
                        queryWrapper.eq(WmsRepertory::getStockOrg, byId.getOrganization());
                    }
                    if (StringUtils.isNotBlank(finalOwnerCode)) {
                        queryWrapper.eq(WmsRepertory::getOwnerCode, finalOwnerCode);
                    }
                    // 查询库存
                    WmsRepertory repertory = this.getOne(queryWrapper);
                    if (ObjectUtil.isNotNull(repertory) && repertory.getStatus().equals(FREEZE)) {
                        throw new JeecgBootException(repertory.getMaterialName() + "物料" + repertory.getBatchCode() + "批次号在即时库存的库存状态为已冻结, 不可入库!");
                    }
                });
        //获取 物料id-是否启用批次号管理 Map
        List<String> materialIdList = inReceiptMaterials.stream().map(WmsInReceiptMaterial::getWmsBasicMaterialId).collect(Collectors.toList());
        List<BasicMaterial> materials = materialService.list(new LambdaQueryWrapper<BasicMaterial>()
                .in(CollectionUtil.isNotEmpty(materialIdList), BasicMaterial::getId, materialIdList)
        );
        Map<String, String> materialIdBatchMap = materials.stream().filter(s -> StringUtils.isNotBlank(s.getMaterialTypeId())).collect(Collectors.toMap(BasicMaterial::getId, BasicMaterial::getBatchManagementFlag));
        // 拿取所有库存信息
        List<WmsRepertory> list = this.list();
        // 需要提示的信息
        ArrayList<WmsRepertory> warning = new ArrayList<>();
        // 遍历待添加的库存对象，检查是否已存在
        inReceiptMaterials.forEach(w -> {
            WmsRepertory repertory = findExistingRepertory(list, w, byId, finalOwnerCode);
            if (ObjectUtil.isNotNull(repertory)) {
                //启用批次号管理的才提示
                if ("1".equals(materialIdBatchMap.get(repertory.getMaterialId()))) {
                    warning.add(repertory);
                }
            }
        });
        return warning;
    }

    @Override
    public List<RepertoryVO> all() {
        List<WmsRepertory> list = this.list(new LambdaQueryWrapper<WmsRepertory>().eq(WmsRepertory::getDelFlag, "0"));
        return BeanUtil.copyToList(list, RepertoryVO.class);
    }

    /**
     * 和已经存在的库存对象进行筛选
     *
     * @param existingRepertories
     * @param w
     * @return org.jeecg.modules.business.repertory.entity.WmsRepertory
     * @author hansen
     * @since 2023/8/25 11:11
     */
    private WmsRepertory findExistingRepertory(List<WmsRepertory> existingRepertories, WmsRepertory w) {
        //对比的时候,因为库存里有仓库库区库位为空字符串的情况,所以先把为null的都赋值为空字符串,再equals
        handleData(existingRepertories, w);
        return existingRepertories.stream()
                .filter(repertory -> repertory.getMaterialId().equals(w.getMaterialId()) &&
                        repertory.getWmsBasicWarehouseId().equals(w.getWmsBasicWarehouseId()) &&
                        Objects.equals(repertory.getWmsBasicWarehouseAreaId(), w.getWmsBasicWarehouseAreaId()) &&
                        Objects.equals(repertory.getWmsBasicWarehouseAreaLocationId(), w.getWmsBasicWarehouseAreaLocationId()) &&
                        repertory.getDelFlag().equals(0) &&
                        Objects.equals(repertory.getOwnerType(), w.getOwnerType()) &&
                        Objects.equals(repertory.getStockOrg(), w.getStockOrg()) &&
                        Objects.equals(repertory.getOwnerCode(), w.getOwnerCode()) &&
                        Objects.equals(repertory.getBatchCode(), w.getBatchCode()))
                .findFirst()
                .orElse(null);
    }
    /**
     * 和已经存在的库存对象进行筛选(有批次号的,只按照物料加批次号匹配)
     *
     * @param existingRepertories
     * @param w
     * @return org.jeecg.modules.business.repertory.entity.WmsRepertory
     * @author hansen
     * @since 2023/8/25 11:11
     */
    private List<WmsRepertory> findExistingRepertory2(List<WmsRepertory> existingRepertories, WmsRepertory w) {
        //对比的时候,因为库存里有仓库库区库位为空字符串的情况,所以先把为null的都赋值为空字符串,再equals
        handleData(existingRepertories, w);
        return existingRepertories.stream()
                .filter(repertory -> repertory.getMaterialId().equals(w.getMaterialId()) &&
                        repertory.getDelFlag().equals(0) &&
                        Objects.equals(repertory.getBatchCode(), w.getBatchCode())).collect(Collectors.toList());
    }

    void handleData(List<WmsRepertory> existingRepertories, WmsRepertory w) {
        //物料、仓库、库区、库位、货主类型、货主编码、库存组织、批次号
        if (w.getWmsBasicWarehouseId() == null) {
            w.setWmsBasicWarehouseId("");
        }
        if (w.getWmsBasicWarehouseAreaId() == null) {
            w.setWmsBasicWarehouseAreaId("");
        }
        if (w.getWmsBasicWarehouseAreaLocationId() == null) {
            w.setWmsBasicWarehouseAreaLocationId("");
        }
        if (w.getBatchCode() == null) {
            w.setBatchCode("");
        }
        if (w.getOwnerType() == null) {
            w.setOwnerType("");
        }
        if (w.getOwnerCode() == null) {
            w.setOwnerCode("");
        }
        if (w.getStockOrg() == null) {
            w.setStockOrg("");
        }
        existingRepertories.forEach(one -> {
            if (one.getWmsBasicWarehouseId() == null) {
                one.setWmsBasicWarehouseId("");
            }
            if (one.getWmsBasicWarehouseAreaId() == null) {
                one.setWmsBasicWarehouseAreaId("");
            }
            if (one.getWmsBasicWarehouseAreaLocationId() == null) {
                one.setWmsBasicWarehouseAreaLocationId("");
            }
            if (one.getBatchCode() == null) {
                one.setBatchCode("");
            }
            if (one.getOwnerType() == null) {
                one.setOwnerType("");
            }
            if (one.getOwnerCode() == null) {
                one.setOwnerCode("");
            }
            if (one.getStockOrg() == null) {
                one.setStockOrg("");
            }
        });
    }

    private WmsRepertory findExistingRepertory(List<WmsRepertory> existingRepertories, WmsInReceiptMaterial w, WmsInReceipt byId, String finalOwnerCode) {
        return existingRepertories.stream()
                .filter(repertory -> repertory.getMaterialId().equals(w.getWmsBasicMaterialId()) &&
                        repertory.getWmsBasicWarehouseId().equals(w.getWmsBasicWarehouseId()) &&
                        Objects.equals(repertory.getWmsBasicWarehouseAreaId(), w.getWmsBasicWarehouseAreaId()) &&
                        Objects.equals(repertory.getWmsBasicWarehouseAreaLocationId(), w.getWmsBasicWarehouseAreaLocationId()) &&
                        repertory.getDelFlag().equals(0) &&
                        Objects.equals(repertory.getOwnerType(), byId.getOwnerType()) &&
                        repertory.getStockOrg().equals(byId.getOrganization()) &&
                        Objects.equals(repertory.getOwnerCode(), finalOwnerCode) &&
                        Objects.equals(repertory.getBatchCode(), w.getBatchCode()))
                .findFirst()
                .orElse(null);
    }

    /**
     * 更新库存数量
     *
     * @param repertory
     * @param w
     * @return void
     * @author hansen
     * @since 2023/8/25 11:12
     */
    private void validateAndUpdate(WmsRepertory repertory, WmsRepertory w) {
        //w: 待添加库存  repertory: 库存中已有库存
//        if (repertory.getLockQuantity() != null && repertory.getLockQuantity().compareTo(BigDecimal.ZERO) > 0) {
//            throw new JeecgBootException(repertory.getMaterialName() + "物料已经被锁定, 不可入库!");
//        }
        if (FREEZE.equals(repertory.getStatus())) {
            throw new JeecgBootException("物料:" + repertory.getMaterialName() + "批次号:" + repertory.getBatchCode() + "在即使库存已经被冻结, 不可入库!");
        }
        String[] ignore = {"id", "stockQuantity", "usableQuantity", "lockQuantity", "status", "stockQuantitySub", "usableQuantitySub", "lockQuantitySub", "createTime", "warehouseDate"};
        BeanUtils.copyProperties(w, repertory, ignore);
        // 可用量
        repertory.setUsableQuantity(repertory.getUsableQuantity().add(w.getUsableQuantity()));
        // 库存量
        repertory.setStockQuantity(repertory.getStockQuantity().add(w.getStockQuantity()));
        // 锁定量
        repertory.setLockQuantity(repertory.getLockQuantity());
        repertory.setWarehouseDate(w.getWarehouseDate());
        repertory.setStockQuantitySub(repertory.getStockQuantitySub().add(w.getStockQuantitySub()));
        repertory.setUsableQuantitySub(repertory.getUsableQuantitySub().add(w.getUsableQuantitySub()));
        repertory.setLockQuantitySub(repertory.getLockQuantitySub());
    }
    private void validateAndUpdate2(WmsRepertory repertory, WmsRepertory w) {
        //w: 待添加库存  repertory: 库存中已有库存
//        if (repertory.getLockQuantity() != null && repertory.getLockQuantity().compareTo(BigDecimal.ZERO) > 0) {
//            throw new JeecgBootException(repertory.getMaterialName() + "物料已经被锁定, 不可入库!");
//        }
        if (FREEZE.equals(repertory.getStatus())) {
            throw new JeecgBootException("物料:" + repertory.getMaterialName() + "批次号:" + repertory.getBatchCode() + "在即使库存已经被冻结, 不可入库!");
        }
        Date date = new Date();
        repertory.setNewestInboundTime(date);
        repertory.setWmsBasicWarehouseId(w.getWmsBasicWarehouseId());
        repertory.setWmsBasicWarehouseAreaId(w.getWmsBasicWarehouseAreaId());
        repertory.setWmsBasicWarehouseAreaLocationId(w.getWmsBasicWarehouseAreaLocationId());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (sysUser != null){
            repertory.setUpdateBy(sysUser.getUsername());
            repertory.setUpdateTime(date);
        }
        // 可用量
        repertory.setUsableQuantity(w.getUsableQuantity());
        // 库存量
        repertory.setStockQuantity(w.getStockQuantity());
        // 锁定量
        repertory.setLockQuantity(repertory.getLockQuantity());
        repertory.setStockQuantitySub(w.getStockQuantitySub());
        repertory.setUsableQuantitySub(w.getUsableQuantitySub());
        repertory.setLockQuantitySub(repertory.getLockQuantitySub());
    }

    private static class Result {
        public final Map<String, WmsBasicWarehouse> warehouseMap;
        public final Map<String, WmsBasicWarehouseArea> areaMap;
        public final Map<String, WmsBasicWarehouseAreaLocation> locationMap;

        public Result(Map<String, WmsBasicWarehouse> warehouseMap, Map<String, WmsBasicWarehouseArea> areaMap, Map<String, WmsBasicWarehouseAreaLocation> locationMap) {
            this.warehouseMap = warehouseMap;
            this.areaMap = areaMap;
            this.locationMap = locationMap;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public org.jeecg.common.api.vo.Result<String> importExcel(HttpServletRequest request, String code) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            // 获取上传文件对象
            MultipartFile file = entity.getValue();
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<WmsRepertory> list = ExcelImportUtil.importExcel(file.getInputStream(), WmsRepertory.class, params);
                for (WmsRepertory one : list) {
                    one.setMaterialCode(addZero(one.getMaterialCode()));
                }

                List<WmsRepertory> addList = new ArrayList<>();
                List<WmsRepertory> updateList = new ArrayList<>();

                int addCount = 0;
                int updateCount = 0;
                List<String> batchCodes = new ArrayList<>();
                WmsRepertory wmsRepertory = null;
                Map<String, WmsSapWarehouseMap> sapCodesMap = new HashMap<>();
                List<String> sapCodes = list.stream().map(t -> t.getWmsBasicWarehouseId()).distinct().collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(sapCodes)) {
                    List<WmsSapWarehouseMap> sapCodesList = wmsSapWarehouseMapService.list(new LambdaQueryWrapper<WmsSapWarehouseMap>().in(WmsSapWarehouseMap::getSapLocation, sapCodes));
                    if (CollectionUtil.isNotEmpty(sapCodesList)) {
                        sapCodesMap = sapCodesList.stream().collect(Collectors.toMap(t -> t.getFactory() + "-" + t.getPlantArea() + "-" + t.getSapLocation() + "-" + t.getWmsBasicWarehouseCode(), a -> a));
                    }
                }
                Map<String, String> basicUnitMap = new HashMap<>();
                Map<String, BasicMaterial> basicMaterialMap = new HashMap<>();
                List<String> materialIds = list.stream().map(t -> t.getMaterialCode()).distinct().collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(materialIds)) {
                    List<BasicMaterial> materialIdsList = basicMaterialService.list(new LambdaQueryWrapper<BasicMaterial>().in(BasicMaterial::getCode, materialIds));
                    if (CollectionUtil.isNotEmpty(materialIdsList)) {
                        basicMaterialMap = materialIdsList.stream().collect(Collectors.toMap(t -> t.getCode(), a -> a));
                        basicUnitMap = materialIdsList.stream().collect(Collectors.toMap(t -> t.getId(), a -> a.getInventoryUnitId()));
                    }
                }

                Map<String, BasicCustomer> basicCustomerMap = new HashMap<>();
                List<String> basicSupplierIds = list.stream().map(t -> t.getWmsBasicSupplierId()).distinct().collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(basicSupplierIds)) {
                    List<BasicCustomer> basicCustomerList = basicCustomerService
                            .list(new LambdaQueryWrapper<BasicCustomer>().in(BasicCustomer::getCode, basicSupplierIds)
                                    .eq(BasicCustomer::getKind, "1"));
                    if (CollectionUtil.isNotEmpty(basicCustomerList)) {
                        basicCustomerMap = basicCustomerList.stream().collect(Collectors.toMap(t -> t.getCode(), a -> a));
                    }
                }

                for (int i = 0; i < list.size(); i++) {
                    if (ObjectUtil.compare(list.get(i).getStockQuantity(), new BigDecimal("0")) == 0) {
                        continue;
                    }
                    wmsRepertory = list.get(i);

                    // 物料
                    if (ObjectUtil.isNotNull(basicUnitMap.get(wmsRepertory.getMaterialId()))) {
                        String unitId = basicUnitMap.get(wmsRepertory.getMaterialId());
                        wmsRepertory.setWmsBasicUnitId(unitId);
                    }

                    if (ObjectUtil.isNotNull(wmsRepertory.getStockQuantity())) {
                        if (ObjectUtil.isNull(wmsRepertory.getMeasuredWeight())) {
                            wmsRepertory.setMeasuredWeight(wmsRepertory.getStockQuantity());
                        }
                        if (ObjectUtil.isNotNull(wmsRepertory.getStockQuantity())) {
                            wmsRepertory.setUsableQuantity(wmsRepertory.getStockQuantity());
                        }
                    }

                    // 仓库sap对照表
                    if (ObjectUtil.isNotNull(sapCodesMap.get(wmsRepertory.getFactory() + "-" + wmsRepertory.getPlantArea() + "-" + wmsRepertory.getWmsBasicWarehouseId() + "-" + code))) {
                        WmsSapWarehouseMap wmsSapWarehouseMap = sapCodesMap.get(wmsRepertory.getFactory() + "-" + wmsRepertory.getPlantArea() + "-" + wmsRepertory.getWmsBasicWarehouseId() + "-" + code);
                        wmsRepertory.setWmsBasicWarehouseId(wmsSapWarehouseMap.getWmsBasicWarehouseId());

                        List<WmsBasicWarehouseArea> areaList = wmsBasicWarehouseAreaService.list(new LambdaQueryWrapper<WmsBasicWarehouseArea>()
                                .eq(WmsBasicWarehouseArea::getWmsBasicWarehouseId, wmsSapWarehouseMap.getWmsBasicWarehouseId()).orderByAsc(WmsBasicWarehouseArea::getName));
                        if (CollectionUtil.isNotEmpty(areaList)) {
                            wmsRepertory.setWmsBasicWarehouseAreaId(areaList.get(0).getId());
                        }
                    }

                    // 物料
                    if (ObjectUtil.isNotNull(basicMaterialMap.get(wmsRepertory.getMaterialCode()))) {
                        BasicMaterial basicMaterial = basicMaterialMap.get(wmsRepertory.getMaterialCode());
                        wmsRepertory.setMaterialId(basicMaterial.getId());
                        wmsRepertory.setMaterialName(basicMaterial.getName());
                    }

                    // 物料
                    if (ObjectUtil.isNotNull(basicCustomerMap.get(wmsRepertory.getWmsBasicSupplierId()))) {
                        BasicCustomer basicCustomer = basicCustomerMap.get(wmsRepertory.getWmsBasicSupplierId());
                        wmsRepertory.setWmsBasicSupplierId(basicCustomer.getId());
                    }

                    // 根据编码查询
                    if (StringUtils.isNotBlank(wmsRepertory.getBatchCode())) {
                        List<WmsRepertory> wmsRepertorys = this.list(new LambdaQueryWrapper<WmsRepertory>().eq(WmsRepertory::getBatchCode, wmsRepertory.getBatchCode()));
                        if (ObjectUtil.isNotEmpty(wmsRepertorys)) {
                            WmsRepertory wmsRepertory1 = wmsRepertorys.get(0);
                            if (wmsRepertorys.size() > 1) {
                                batchCodes.add(wmsRepertory.getBatchCode());
                            }
                            BeanUtils.copyProperties(wmsRepertory, wmsRepertory1, "id");
                            updateList.add(wmsRepertory1);
                        } else {
                            addList.add(wmsRepertory);
                        }

                    }
                    if (CollectionUtil.isNotEmpty(addList) && i % 1000 == 0) {
                        this.saveBatch(addList);
                        addCount += addList.size();
                        // 同步sap库存时对新增的物料查询是否存存在未完成的入库任务，有则关闭任务
                        if (CollectionUtil.isNotEmpty(addList)) {
                            compareBatchCodeCloseTask(addList);
                        }
                        addList = new ArrayList<>();
                    }
                    if (CollectionUtil.isNotEmpty(updateList) && i % 1000 == 0) {
                        this.updateBatchById(updateList);
                        updateCount += updateList.size();
                        updateList = new ArrayList<>();
                    }
                }
                if (CollectionUtil.isNotEmpty(addList)) {
                    addCount += addList.size();
                    this.saveBatch(addList);
                }
                if (CollectionUtil.isNotEmpty(updateList)) {
                    updateCount += updateList.size();
                    this.updateBatchById(updateList);
                }
                // 同步sap库存时对新增的物料查询是否存存在未完成的入库任务，有则关闭任务
                if (CollectionUtil.isNotEmpty(addList)) {
                    compareBatchCodeCloseTask(addList);
                }
                log.info("导入共计：" + list.size() + ",更新：" + updateCount + ",新增：" + addCount);
                log.info("重复的编码：" + (CollectionUtil.isNotEmpty(batchCodes) ? batchCodes.stream().collect(Collectors.joining(",")) : ""));
                return org.jeecg.common.api.vo.Result.OK("文件导入成功！数据行数：" + list.size());
            } catch (Exception e) {
                String msg = e.getMessage();
                log.error(msg, e);
                if (msg != null && msg.indexOf("Duplicate entry") >= 0) {
                    return org.jeecg.common.api.vo.Result.error("文件导入失败:有重复数据！");
                } else {
                    return org.jeecg.common.api.vo.Result.error("文件导入失败:" + e.getMessage());
                }
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return org.jeecg.common.api.vo.Result.error("文件导入失败！");
    }

    @Override
    public List<RepertoryTcVO> listTcByPage(RepertoryTcParamVO param) {

        LambdaQueryWrapper<WmsRepertory> wrapper = new LambdaQueryWrapper<>();
        List<RepertoryTcVO> result = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(param.getWmsStoreCodes())) {
            List<WmsBasicWarehouse> list = warehouseService.list(new LambdaQueryWrapper<WmsBasicWarehouse>().in(WmsBasicWarehouse::getCode, param.getWmsStoreCodes()));
            List<String> ids = list.stream().map(t -> t.getId()).collect(Collectors.toList());
            if (CollectionUtil.isEmpty(ids)) {
                throw new JeecgBootException("提供的仓库编码有误");
            }
            wrapper.in(WmsRepertory::getWmsBasicWarehouseId, ids);
        }
        if (param.getType() == 1) {
            // 刻痕编码
            BasicMaterial khtlMaterial = basicMaterialService.getByCode(khtlCode);
            wrapper.ne(WmsRepertory::getMaterialId, khtlMaterial.getId());
        }

        List<WmsRepertory> repertorys = new ArrayList<>();
        if (ObjectUtil.isNotNull(param.getPageNo()) && ObjectUtil.isNotNull(param.getPageSize())) {
            Page<WmsRepertory> page = new Page<>(param.getPageNo(), param.getPageSize());
            IPage<WmsRepertory> wmsRepertoryPage = wmsRepertoryMapper.selectPage(page, wrapper);
            repertorys = wmsRepertoryPage.getRecords();
        } else {
            repertorys = wmsRepertoryMapper.selectList(wrapper);
        }

        if (CollectionUtil.isNotEmpty(repertorys)) {

            List<String> unitIds = repertorys.stream().map(t -> t.getWmsBasicUnitId()).distinct().collect(Collectors.toList());
            List<BasicUnit> basicUnitList = basicUnitService.list(new LambdaQueryWrapper<BasicUnit>().in(BasicUnit::getId, unitIds));
            Map<String, String> unitMap = basicUnitList.stream().collect(Collectors.toMap(t -> t.getId(), a -> a.getCode()));

            List<String> basicWarehouseIds = repertorys.stream().map(t -> t.getWmsBasicWarehouseId()).collect(Collectors.toList());
            List<WmsBasicWarehouse> list = warehouseService.list(new LambdaQueryWrapper<WmsBasicWarehouse>().in(WmsBasicWarehouse::getId, basicWarehouseIds));
            Map<String, String> warehouseMap = list.stream().collect(Collectors.toMap(t -> t.getId(), a -> a.getCode()));

            if(param.getType() == 1){
                // 处理原卷刻痕批次特性
                getPeculiaritys(repertorys);
            }

            result = BeanUtil.copyToList(repertorys, RepertoryTcVO.class);
            if (CollectionUtil.isNotEmpty(warehouseMap)) {
                result.stream().forEach(t -> {
                    if (ObjectUtil.isNotNull(warehouseMap.get(t.getWmsBasicWarehouseId()))) {
                        String wmsSapWarehouseCode = warehouseMap.get(t.getWmsBasicWarehouseId());
                        t.setWmsStoreLocation(wmsSapWarehouseCode);
                    }

                    if (ObjectUtil.isNotNull(unitMap.get(t.getWmsBasicUnitId()))) {
                        String unitCode = unitMap.get(t.getWmsBasicUnitId());
                        t.setUnitCode(unitCode);
                    }
                });
            }
        }

        return result;
    }

    /**
     * 获取批次特性并更新
     * @param repertorys
     */
    private void getPeculiaritys(List<WmsRepertory> repertorys){
        List<WmsRepertory> waitUpdates = repertorys.stream().filter(t->
                ObjectUtil.isEmpty(t.getWidth())
                        || ObjectUtil.isEmpty(t.getOutsideDiameter())
                        || ObjectUtil.compare(t.getWidth(),new BigDecimal("0"))==0
                        || ObjectUtil.compare(t.getOutsideDiameter(),new BigDecimal("0"))==0
        ).collect(Collectors.toList());
        List<MaterialBatchPeculiarityDTO> list = new ArrayList<>();

        List<String> materialIds = waitUpdates.stream().filter(t -> StringUtils.isBlank(t.getMaterialCode())).map(t -> t.getMaterialId()).collect(Collectors.toList());
        Map<String, String> basicMaterialMap = new HashMap<>();
        if(CollectionUtil.isNotEmpty(materialIds)){
            List<BasicMaterial> basicMaterialList = basicMaterialService.list(new LambdaQueryWrapper<BasicMaterial>().in(BasicMaterial::getId, materialIds));
            basicMaterialMap = basicMaterialList.stream().collect(Collectors.toMap(t -> t.getId(), a -> a.getCode()));
        }
        Map<String, String> finalbasicMaterialMap = basicMaterialMap;
        String uid = IdUtil.fastSimpleUUID();
        waitUpdates.stream().forEach(t->{
            MaterialBatchPeculiarityDTO materialBatchPeculiarityDTO = new MaterialBatchPeculiarityDTO();
            materialBatchPeculiarityDTO.setUuid(uid);

            if(StringUtils.isBlank(t.getMaterialCode())){
                String materialCode = finalbasicMaterialMap.get(t.getMaterialId());
                materialBatchPeculiarityDTO.setMaterial(materialCode);
            }else{
                materialBatchPeculiarityDTO.setMaterial(t.getMaterialCode());
            }

            materialBatchPeculiarityDTO.setBatch(t.getBatchCode());
            list.add(materialBatchPeculiarityDTO);
        });
        List<MaterialBatchPeculiarityResponseDTO> materialBatchPeculiarityResponseDTOS = sapDockingRepeaterService.materialPeculiarity(list);

        if(CollectionUtil.isNotEmpty(materialBatchPeculiarityResponseDTOS)){
            Map<String, MaterialBatchPeculiarityResponseDTO> peculiarityMap = materialBatchPeculiarityResponseDTOS.stream().collect(Collectors.toMap(t -> t.getBatchCode(), a -> a));
            waitUpdates.stream().forEach(t->{
                MaterialBatchPeculiarityResponseDTO materialBatchPeculiarityResponseDTO = peculiarityMap.get(t.getBatchCode());
                if(ObjectUtil.isNotEmpty(materialBatchPeculiarityResponseDTO)){
                    t.setWidth(new BigDecimal(String.valueOf(materialBatchPeculiarityResponseDTO.getSteelCoilWidth())));
                    t.setOutsideDiameter(new BigDecimal(String.valueOf(materialBatchPeculiarityResponseDTO.getOuterDiameterSize())));
                    if(StringUtils.isBlank(t.getMaterialCode())){
                        String materialCode = finalbasicMaterialMap.get(t.getMaterialId());
                        t.setMaterialCode(materialCode);
                    }
                }
            });
            this.updateBatchById(waitUpdates);

            repertorys.stream().forEach(t->{
                MaterialBatchPeculiarityResponseDTO materialBatchPeculiarityResponseDTO = peculiarityMap.get(t.getBatchCode());
                if(ObjectUtil.isNotEmpty(materialBatchPeculiarityResponseDTO)){
                    t.setWidth(new BigDecimal(String.valueOf(materialBatchPeculiarityResponseDTO.getSteelCoilWidth())));
                    t.setOutsideDiameter(new BigDecimal(String.valueOf(materialBatchPeculiarityResponseDTO.getOuterDiameterSize())));
                    if(StringUtils.isBlank(t.getMaterialCode())){
                        String materialCode = finalbasicMaterialMap.get(t.getMaterialId());
                        t.setMaterialCode(materialCode);
                    }
                }
            });
        }
    }

    @Override
    public MesBaseResponseVO getLocation(RepertoryRequestParam param) {
        if (param.getType() == 1 || param.getType() == 2 || param.getType() == 3) {
            return MesBaseResponseVO.ok(wmsRepertoryMapper.getLocation(param));
        }
        return MesBaseResponseVO.failure("类型未找到");
    }

    @Override
    public void updateRawFeature(List<WmsRepertory> wmsRepertories) {
        try {
            List<String> materialIds = wmsRepertories.stream().filter(t -> StringUtils.isBlank(t.getMaterialCode())).map(t -> t.getMaterialId()).collect(Collectors.toList());
            Map<String, String> basicMaterialMap = new HashMap<>();
            if(CollectionUtil.isNotEmpty(materialIds)){
                List<BasicMaterial> basicMaterialList = basicMaterialService.list(new LambdaQueryWrapper<BasicMaterial>().in(BasicMaterial::getId, materialIds));
                basicMaterialMap = basicMaterialList.stream().collect(Collectors.toMap(t -> t.getId(), a -> a.getCode()));
            }
            Map<String, String> finalbasicMaterialMap = basicMaterialMap;

            List<MaterialBatchPeculiarityDTO> list = new ArrayList<>();
            String uid = IdUtil.fastSimpleUUID();
            wmsRepertories.stream().forEach(t->{
                MaterialBatchPeculiarityDTO materialBatchPeculiarityDTO = new MaterialBatchPeculiarityDTO();
                materialBatchPeculiarityDTO.setUuid(uid);

                if(StringUtils.isBlank(t.getMaterialCode())){
                    String materialCode = finalbasicMaterialMap.get(t.getMaterialId());
                    materialBatchPeculiarityDTO.setMaterial(materialCode);
                }else{
                    materialBatchPeculiarityDTO.setMaterial(t.getMaterialCode());
                }
                if(StringUtils.isNotBlank(t.getBatchCode())
                        && !bzxjlCode.equals(t.getMaterialCode())
                        && !khtlCode.equals(t.getMaterialCode())){
                    materialBatchPeculiarityDTO.setBatch(t.getBatchCode());
                    list.add(materialBatchPeculiarityDTO);
                }
            });

            if(CollectionUtil.isEmpty(list)){
                return;
            }
            List<MaterialBatchPeculiarityResponseDTO> materialBatchPeculiarityResponseDTOS = sapDockingRepeaterService.materialPeculiarity(list);
            if(CollectionUtil.isEmpty(materialBatchPeculiarityResponseDTOS)) {
                return;
            }

            Map<String, MaterialBatchPeculiarityResponseDTO> peculiarityMap = materialBatchPeculiarityResponseDTOS.stream().collect(Collectors.toMap(t -> t.getBatchCode(), a -> a));
            wmsRepertories.stream().forEach(t->{
                MaterialBatchPeculiarityResponseDTO responseDTO = peculiarityMap.get(t.getBatchCode());
                if(ObjectUtil.isNotEmpty(responseDTO)){
                    t.setWidth(NumberUtil.toBigDecimal(responseDTO.getSteelCoilWidth()));
                    t.setOutsideDiameter(NumberUtil.toBigDecimal(responseDTO.getOuterDiameterSize()));
                    if(StringUtils.isBlank(t.getMaterialCode())){
                        String materialCode = finalbasicMaterialMap.get(t.getMaterialId());
                        t.setMaterialCode(materialCode);
                    }
                    t.setMeasuredWeight(NumberUtil.toBigDecimal(responseDTO.getMeasuredWeight()));
                    t.setGrossWeight(NumberUtil.toBigDecimal(responseDTO.getProductWeight()));
                    t.setSteelCode(responseDTO.getSteelCoilNumber());
                    t.setShopSign(String.valueOf(responseDTO.getSteelCoilBrand()));
                    t.setIronLoss(NumberUtil.toBigDecimal(responseDTO.getIronLossValue1()));
                    t.setAppearanceGrade(responseDTO.getAppearanceGrade());
                }
            });
        }catch (Exception e){
            log.error("更新原料批次特新异常",e);
        }
    }

    /**
     * 同步sap库存时对新增的物料查询是否存存在未完成的入库任务，有则关闭任务
     *
     * @param list
     */
    public void compareBatchCodeCloseTask(List<WmsRepertory> list) {
        List<String> waitDealBatCodes = list.stream().map(t -> t.getBatchCode()).distinct().collect(Collectors.toList());
        List<List<String>> waitDealBatCodesList = groupListByQuantity(waitDealBatCodes, 500);
        List<String> noDealTaskIds = new ArrayList<>();
        List<String> noReceiptIds = new ArrayList<>();
        for (List<String> dealCuttentBatCodes : waitDealBatCodesList) {
            List<WmsInReceiptTaskMaterial> wmsInReceiptTaskMaterials = wmsInReceiptTaskMaterialService.list(new LambdaQueryWrapper<WmsInReceiptTaskMaterial>().in(WmsInReceiptTaskMaterial::getBatchCode, dealCuttentBatCodes));
            if (CollectionUtil.isNotEmpty(wmsInReceiptTaskMaterials)) {
                List<String> wmsInReceiptTaskIds = wmsInReceiptTaskMaterials.stream()
                        .filter(t -> ObjectUtil.compare(t.getPlanQuantity(), t.getWarehousedQuantity()) > 0)
                        .map(t -> t.getWmsInReceiptTaskId()).distinct().collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(wmsInReceiptTaskIds)) {
                    wmsInReceiptTaskIds.stream().forEach(t -> {
                        BaseFlowDto base = new BaseFlowDto();
                        base.setInfoId(t);
                        base.setRefuseType(2);
                        try {
                            workFlowService.interrupt(base);
                        } catch (Exception e) {
                            log.error("关闭入库任务流程存在异常:[{}]", t, e);
                            noDealTaskIds.add(t);
                        }

                    });
                }
            }

            List<WmsInReceiptMaterial> wmsInReceiptMaterials = wmsInReceiptMaterialService.list(new LambdaQueryWrapper<WmsInReceiptMaterial>().in(WmsInReceiptMaterial::getBatchCode, dealCuttentBatCodes));
            if (CollectionUtil.isNotEmpty(wmsInReceiptMaterials)) {
                List<String> wmsInReceiptIds = wmsInReceiptMaterials.stream()
                        .filter(t -> ObjectUtil.compare(t.getReceivableQuantity(), t.getWarehouseQuantity()) > 0)
                        .map(t -> t.getWmsInReceiptId()).distinct().collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(wmsInReceiptIds)) {
                    wmsInReceiptIds.stream().forEach(t -> {
                        BaseFlowDto base = new BaseFlowDto();
                        base.setInfoId(t);
                        base.setRefuseType(2);
                        try {
                            workFlowService.interrupt(base);
                        } catch (Exception e) {
                            log.error("关闭入库单流程存在异常:[{}]", t, e);
                            noReceiptIds.add(t);
                        }
                    });
                }
            }
        }
        if (CollectionUtil.isNotEmpty(noDealTaskIds)) {
            log.error("关闭入库任务流程存在异常的任务id集合如下：【{}】", noDealTaskIds.stream().collect(Collectors.joining(",")));
        }
        if (CollectionUtil.isNotEmpty(noReceiptIds)) {
            log.error("关闭入库单流程存在异常的任务id集合如下：【{}】", noReceiptIds.stream().collect(Collectors.joining(",")));
        }

    }

    /**
     * 将集合按指定数量分组
     *
     * @param list     数据集合
     * @param quantity 分组数量
     * @return 分组结果
     */
    public static <T> List<List<String>> groupListByQuantity(List<String> list, int quantity) {
        if (list == null || list.size() == 0) {
            return null;
        }

        if (quantity <= 0) {
            throw new IllegalArgumentException("Wrong quantity.");
        }

        List<List<String>> wrapList = new ArrayList<List<String>>();
        int count = 0;
        while (count < list.size()) {
            wrapList.add(new ArrayList<String>(list.subList(count, Math.min((count + quantity), list.size()))));
            count += quantity;
        }

        return wrapList;
    }


}
